Add selectable native LTX Original runtime and DeskWEB API integration
This commit is contained in:
@@ -7,7 +7,7 @@ from auth import atomic_write,validate_record
|
||||
from backup_codec import seal,open_backup
|
||||
from catalog import repo_id,file_role,KINDS
|
||||
from profiles import SCHEMAS,CHAT_GPU_DEFAULTS,chat_parameters
|
||||
SETTINGS=('profiles.json','endpoint.json','audio-policy.json','video/comfy-selection.json','models/huggingface.json','video/comfy-client-token')
|
||||
SETTINGS=('profiles.json','endpoint.json','audio-policy.json','video/comfy-selection.json','models/huggingface.json','video/comfy-client-token','video/original-work/settings.json')
|
||||
MAX_HISTORY=40*1024**2
|
||||
VERSION=1
|
||||
# Exact byte hash verified against official Hub metadata, not a filename heuristic.
|
||||
@@ -63,14 +63,17 @@ def validate(doc):
|
||||
policy=settings.get('audio-policy.json',{})
|
||||
if not isinstance(policy,dict) or set(policy)-{'tts','stt'} or any(not isinstance(v,dict) or set(v)!={'mode','profile_id'} or v['mode'] not in ('auto','warm','per_request') or v['profile_id'] is not None and v['profile_id'] not in pids for v in policy.values()):raise ValueError('Ungültige Audio-Einstellung.')
|
||||
selection=settings.get('video/comfy-selection.json',{})
|
||||
if not isinstance(selection,dict) or set(selection)-{'model_id'} or selection.get('model_id') and selection['model_id'] not in ids:raise ValueError('Ungültige Video-Auswahl.')
|
||||
if isinstance(selection,dict) and selection.get('runtime','comfy') not in ('comfy','original'):raise ValueError('Unbekannte Video-Laufzeit.')
|
||||
if not isinstance(selection,dict) or set(selection)-{'model_id','runtime'} or selection.get('model_id') and selection['model_id'] not in ids:raise ValueError('Ungültige Video-Auswahl.')
|
||||
if 'models/huggingface.json' in settings:
|
||||
hf=settings['models/huggingface.json']
|
||||
if not isinstance(hf,dict) or set(hf)!={'token'} or hf['token'] is not None and (not isinstance(hf['token'],str) or not re.fullmatch(r'hf_[A-Za-z0-9]{10,252}',hf['token'])):raise ValueError('Ungültiger Hugging-Face-Zugang.')
|
||||
if 'video/comfy-client-token' in settings and not re.fullmatch(r'[A-Za-z0-9_-]{32,256}',settings['video/comfy-client-token'].strip()):raise ValueError('Ungültiger Diensttoken.')
|
||||
if 'video/original-work/settings.json' in settings and (not isinstance(settings['video/original-work/settings.json'],dict) or len(json.dumps(settings['video/original-work/settings.json']))>65536):raise ValueError('Ungültige LTX-Einstellungen.')
|
||||
validate_record(doc.get('credentials'))
|
||||
runtimes=doc.get('runtimes')
|
||||
if not isinstance(runtimes,dict) or set(runtimes)!={'llama','llama_builds','image','tts','enhancers','swarm_nodes'}:raise ValueError('Ungültiges Laufzeitrezept.')
|
||||
if not isinstance(runtimes,dict) or set(runtimes)-{'llama','llama_builds','image','tts','enhancers','swarm_nodes','ltx_original'} or not {'llama','llama_builds','image','tts','enhancers','swarm_nodes'}<=set(runtimes):raise ValueError('Ungültiges Laufzeitrezept.')
|
||||
if 'ltx_original' in runtimes and type(runtimes['ltx_original']) is not bool:raise ValueError('Ungültige LTX-Laufzeit.')
|
||||
if not isinstance(runtimes['llama_builds'],list) or len(runtimes['llama_builds'])>50 or any(not isinstance(b,dict) or set(b)!={'commit','backend'} or not re.fullmatch('[a-f0-9]{40}',b.get('commit','')) or b.get('backend') not in ('CUDA','CPU') for b in runtimes['llama_builds']):raise ValueError('Ungültige Buildrezepte.')
|
||||
if runtimes['llama'] is not None:
|
||||
item=runtimes['llama']
|
||||
@@ -134,7 +137,10 @@ class Backup:
|
||||
if not s.network.disabled:
|
||||
network=s.network.call('backup-export')
|
||||
else:warnings.append('Deck-Netzwerkmodul deaktiviert; fremder WireGuard-Gateway wird nicht gesichert.')
|
||||
document=dict(format='athena-deck',version=VERSION,created_at=time.time(),settings=settings,models=models,credentials=s.credentials.read(),theme=theme,network=network,services=services,runtime_versions=dict(image=dict(comfy=s.image_runtime.status()['comfy_revision'],gguf=s.image_runtime.status()['gguf_revision']),tts=s.tts_runtime.status()['revision']),runtimes=dict(llama=llama,llama_builds=[dict(commit=b['commit'],backend=b['backend']) for b in state['builds']],image=s.image_runtime.status()['installed'],tts=s.tts_runtime.status()['installed'],enhancers={task:data['revision'] for task in ('t2i','i2i') if (data:=s.prompt_enhancer.installed(task))},swarm_nodes=(self.root/'video/swarm-comfy-nodes').is_dir()),warnings=warnings)
|
||||
document=dict(format='athena-deck',version=VERSION,created_at=time.time(),settings=settings,models=models,credentials=s.credentials.read(),theme=theme,network=network,services=services,runtime_versions=dict(image=dict(comfy=s.image_runtime.status()['comfy_revision'],gguf=s.image_runtime.status()['gguf_revision']),tts=s.tts_runtime.status()['revision']),runtimes=dict(ltx_original=bool(getattr(s,'ltx_original_runtime',None) and s.ltx_original_runtime.status()['installed']),llama=llama,llama_builds=[dict(commit=b['commit'],backend=b['backend']) for b in state['builds']],image=s.image_runtime.status()['installed'],tts=s.tts_runtime.status()['installed'],enhancers={task:data['revision'] for task in ('t2i','i2i') if (data:=s.prompt_enhancer.installed(task))},swarm_nodes=(self.root/'video/swarm-comfy-nodes').is_dir()),warnings=warnings)
|
||||
if document['runtimes']['ltx_original']:
|
||||
from ltx_original_runtime import DESKTOP_REV,LTX_REV
|
||||
document['runtime_versions']['ltx_original']=dict(desktop=DESKTOP_REV,inference=LTX_REV)
|
||||
if include_history:
|
||||
with tempfile.TemporaryDirectory(dir=self.directory) as work:
|
||||
out=Path(work)/'history.sqlite3'
|
||||
@@ -161,7 +167,10 @@ class Backup:
|
||||
elif s.network.status().get('enabled') or s.network.status().get('mode')!='lan':blockers.append('Deck-Tunnel vor Netzwerk-Restore im bestätigten LAN-Modus deaktivieren.')
|
||||
if doc['network']['mode']!='lan':warnings.append('Tunnelzugang wird mit Rückfallzeit aktiviert und muss über den Tunnel bestätigt werden.')
|
||||
versions=doc.get('runtime_versions',{})
|
||||
if versions and versions!=dict(image=dict(comfy=s.image_runtime.status()['comfy_revision'],gguf=s.image_runtime.status()['gguf_revision']),tts=s.tts_runtime.status()['revision']):blockers.append('Backup verlangt andere Bild-/TTS-Laufzeitversionen. Passende Deck-Version oder geprüftes Runtime-Upgrade verwenden.')
|
||||
if versions.get('ltx_original'):
|
||||
from ltx_original_runtime import DESKTOP_REV,LTX_REV
|
||||
if versions['ltx_original']!=dict(desktop=DESKTOP_REV,inference=LTX_REV):blockers.append('Backup verlangt eine andere originale LTX-Version. Passende Deck-Version verwenden.')
|
||||
if versions and {k:v for k,v in versions.items() if k!='ltx_original'}!=dict(image=dict(comfy=s.image_runtime.status()['comfy_revision'],gguf=s.image_runtime.status()['gguf_revision']),tts=s.tts_runtime.status()['revision']):blockers.append('Backup verlangt andere Bild-/TTS-Laufzeitversionen. Passende Deck-Version oder geprüftes Runtime-Upgrade verwenden.')
|
||||
for c in doc['services']:
|
||||
if not c.get('registry') and c.get('build_recipe')!='swarm-ui':warnings.append(c['name']+': Image nur lokal vorhanden; Registry-/Buildquelle fehlt.')
|
||||
ports=s.endpoint.allowed_ports
|
||||
@@ -186,7 +195,7 @@ class Backup:
|
||||
if len(set(data['services']))!=len(data['services']) or any(name not in services for name in data['services']):raise ValueError('Unbekannter Zusatzdienst.')
|
||||
if any(not services[name].get('registry') and not services[name].get('build_recipe') for name in data['services']):raise ValueError('Gewählter Dienst hat keine Wiederherstellungsquelle.')
|
||||
s=self.server
|
||||
if s.catalog.pending or s.catalog.job and s.catalog.job['state']=='downloading' or s.runtime.busy or any((getattr(o,'job',None) or {}).get('state')=='running' for o in (s.image_runtime,s.tts_runtime,s.prompt_enhancer,s.auto_tests,s.chat_tests,s.image_tests,s.tts_tests,s.stt)):raise ValueError('Zuerst laufende Downloads, Builds und Tests abschließen oder abbrechen.')
|
||||
if s.catalog.pending or s.catalog.job and s.catalog.job['state']=='downloading' or s.runtime.busy or any((getattr(o,'job',None) or {}).get('state')=='running' for o in (s.image_runtime,s.tts_runtime,s.ltx_original_runtime,s.prompt_enhancer,s.auto_tests,s.chat_tests,s.image_tests,s.tts_tests,s.stt)):raise ValueError('Zuerst laufende Downloads, Builds und Tests abschließen oder abbrechen.')
|
||||
self.cancel.clear();self.job=dict(id=secrets.token_hex(16),state='running',phase='Wiederherstellung vorbereiten',completed=0,total=len(doc['models'])+len(data['services'])+5,items=[],started_at=time.time(),theme=doc.get('theme','deck'))
|
||||
self._save();threading.Thread(target=self._restore,args=(copy.deepcopy(doc),data['services'],data['restore_credentials']),daemon=True).start();self.plan=None
|
||||
return self.status()
|
||||
@@ -212,6 +221,8 @@ class Backup:
|
||||
self._phase('Vorhandene Bild-/Videolaufzeit prüfen oder installieren');s.image_runtime.start();self._wait(s.image_runtime.status)
|
||||
if r['tts'] and not s.tts_runtime.status()['installed']:
|
||||
self._phase('TTS-Laufzeit und Zusatzdateien installieren');s.tts_runtime.start();self._wait(s.tts_runtime.status)
|
||||
if r.get('ltx_original') and not s.ltx_original_runtime.status()['installed']:
|
||||
self._phase('Originale LTX-Laufzeit installieren');s.ltx_original_runtime.start();self._wait(s.ltx_original_runtime.status)
|
||||
targets=r['llama_builds']+([r['llama']] if r['llama'] and r['llama'] not in r['llama_builds'] else [])
|
||||
for target in targets:
|
||||
state=s.runtime.status();matching=next((b for b in state['builds'] if b['commit']==target['commit'] and b['backend']==target['backend']),None)
|
||||
@@ -349,5 +360,5 @@ class Backup:
|
||||
with self.lock:
|
||||
self.cancel.set()
|
||||
if self.busy():
|
||||
self.server.catalog.stop();self.server.runtime.stop();self.server.image_runtime.stop();self.server.tts_runtime.stop();self.server.prompt_enhancer.stop()
|
||||
self.server.catalog.stop();self.server.runtime.stop();self.server.image_runtime.stop();self.server.tts_runtime.stop();self.server.ltx_original_runtime.stop();self.server.prompt_enhancer.stop()
|
||||
return {'cancellation_requested':True}
|
||||
|
||||
Reference in New Issue
Block a user