Persist library profiles and download history with weight capacity checks
This commit is contained in:
@@ -7,6 +7,8 @@ import secrets
|
||||
from http.cookies import SimpleCookie, CookieError
|
||||
from auth import CredentialStore, verify_password
|
||||
from catalog import Catalog
|
||||
from profiles import Profiles
|
||||
from capacity import assess, overview
|
||||
from runtime import Runtime
|
||||
from urllib.parse import urlsplit, parse_qs
|
||||
from network.client import NetworkClient
|
||||
@@ -99,6 +101,7 @@ class Server(ThreadingHTTPServer):
|
||||
super().__init__((os.environ.get('DECK_BIND_HOST','127.0.0.1'), port), Handler)
|
||||
self.catalog = Catalog(Path(state_dir or os.environ.get("DECK_STATE_DIR", ROOT/".state"))/"models")
|
||||
self.runtime = Runtime(Path(state_dir or os.environ.get("DECK_STATE_DIR", ROOT/".state"))/"runtime")
|
||||
self.profiles = Profiles(self.catalog.root.parent/"profiles.json",self.catalog)
|
||||
self.demo = DemoService()
|
||||
self.hardware = HardwareProvider()
|
||||
self.started = time.time()
|
||||
@@ -262,12 +265,14 @@ class Handler(BaseHTTPRequestHandler):
|
||||
return self.respond({'error':'Anmeldung erforderlich.'},401)
|
||||
if not self.authenticated() and self.path == '/':
|
||||
return self.respond((ROOT/'login.html').read_bytes(), mime='text/html; charset=utf-8')
|
||||
routes = {'/': ('index.html', 'text/html; charset=utf-8'), '/app.js': ('app.js', 'text/javascript'), '/style.css': ('style.css', 'text/css'), '/network-ui.js': ('network-ui.js', 'text/javascript'), '/access-ui.js': ('access-ui.js', 'text/javascript'), '/studio.js': ('studio.js', 'text/javascript'), '/catalog-ui.js': ('catalog-ui.js','text/javascript'), '/runtime-ui.js': ('runtime-ui.js','text/javascript')}
|
||||
routes = {'/': ('index.html', 'text/html; charset=utf-8'), '/app.js': ('app.js', 'text/javascript'), '/style.css': ('style.css', 'text/css'), '/network-ui.js': ('network-ui.js', 'text/javascript'), '/access-ui.js': ('access-ui.js', 'text/javascript'), '/studio.js': ('studio.js', 'text/javascript'), '/catalog-ui.js': ('catalog-ui.js','text/javascript'), '/runtime-ui.js': ('runtime-ui.js','text/javascript'), '/profiles-ui.js': ('profiles-ui.js','text/javascript')}
|
||||
if self.path in routes:
|
||||
name, mime = routes[self.path]
|
||||
return self.respond((ROOT/name).read_bytes(), mime=mime)
|
||||
if self.path == '/api/v1/status':
|
||||
return self.respond(dict(name='Athena Deck', version='0.6.0', state='ready', uptime_seconds=round(time.time()-self.server.started), mode='isolated', location=os.environ.get('DECK_LOCATION', 'Athena · Debian-Server'), demo=self.server.demo.status()))
|
||||
if self.path == '/api/v1/profiles':
|
||||
return self.respond(self.server.profiles.status())
|
||||
if self.path == '/api/v1/hardware':
|
||||
return self.respond(self.server.hardware.snapshot())
|
||||
if self.path.startswith('/api/v1/runtime'):
|
||||
@@ -279,7 +284,13 @@ class Handler(BaseHTTPRequestHandler):
|
||||
try:
|
||||
path=urlsplit(self.path);q=parse_qs(path.query)
|
||||
if path.path=='/api/v1/catalog/search':return self.respond(self.server.catalog.search(q.get('q',[''])[0],q.get('kind',['chat'])[0]))
|
||||
if path.path=='/api/v1/catalog/files':return self.respond(self.server.catalog.files(q.get('repo',[''])[0]))
|
||||
if path.path=='/api/v1/catalog/assessment':
|
||||
data=self.server.catalog.files(q.get('repo',[''])[0])
|
||||
return self.respond(overview(data['files'],self.server.hardware.snapshot()))
|
||||
if path.path=='/api/v1/catalog/files':
|
||||
data=dict(self.server.catalog.files(q.get('repo',[''])[0]));hardware=self.server.hardware.snapshot()
|
||||
data['files']=[dict(f,assessment=assess(f['size'],hardware,f['name'])) for f in data['files']]
|
||||
return self.respond(data)
|
||||
if path.path=='/api/v1/catalog':return self.respond(self.server.catalog.status())
|
||||
except Exception as exc:
|
||||
return self.respond({'error':str(exc) if isinstance(exc,ValueError) else 'Katalog nicht erreichbar.'},400)
|
||||
@@ -329,10 +340,15 @@ class Handler(BaseHTTPRequestHandler):
|
||||
raise ValueError('Ungültige Laufzeitaktion.')
|
||||
except ValueError as exc:return self.respond({'error':str(exc)},400)
|
||||
except (OSError, subprocess.SubprocessError):return self.respond({'error':'Laufzeitaktion fehlgeschlagen; Speicher und Werkzeuge prüfen.'},503)
|
||||
if self.path in ('/api/v1/catalog/download','/api/v1/catalog/cancel'):
|
||||
if self.path == '/api/v1/profiles/save':
|
||||
try:return self.respond(self.server.profiles.save(self.read_json()))
|
||||
except ValueError as exc:return self.respond({'error':str(exc)},400)
|
||||
except OSError:return self.respond({'error':'Profil konnte nicht gespeichert werden.'},503)
|
||||
if self.path in ('/api/v1/catalog/download','/api/v1/catalog/cancel','/api/v1/catalog/dismiss'):
|
||||
try:
|
||||
data=self.read_json()
|
||||
if self.path.endswith('/cancel'):return self.respond(self.server.catalog.stop())
|
||||
if self.path.endswith('/dismiss') and set(data)=={'id'}:return self.respond(self.server.catalog.dismiss(data['id']))
|
||||
if self.path.endswith('/cancel') and not data:return self.respond(self.server.catalog.stop())
|
||||
if set(data)!={'repo','filename','revision','kind'}:raise ValueError('Ungültige Downloadparameter.')
|
||||
return self.respond(self.server.catalog.start(**data))
|
||||
except Exception as exc:
|
||||
|
||||
Reference in New Issue
Block a user