diff --git a/TODO.md b/TODO.md
index 1c5d89da1..e72f7fcf9 100644
--- a/TODO.md
+++ b/TODO.md
@@ -11,12 +11,9 @@ N/A
Stuff to be added, in no particular order...
- Diffusers:
- - Add Lyco support
- Add ControlNet
- - Fix DeepFloyd IF model
- Add unCLIP model
- Add Training support
- - Add long prompts
- Technical debt:
- Port **A1111** stuff
- Port `p.all_hr_prompts`
@@ -24,15 +21,11 @@ Stuff to be added, in no particular order...
- Non-technical:
- Update Wiki
- Rename repo: **automatic** -> **sdnext**
- - [Localization](https://app.transifex.com/signup/open-source/)
- New Minor
- Prompt padding for positive/negative
- - Add EN provider for VAEs
- - Built-in `motd`-style notifications
- New Major
- Profile manager (for `config.json` and `ui-config.json`)
- Multi-user support
- - Add [SAG](https://huggingface.co/docs/diffusers/v0.19.3/en/api/pipelines/self_attention_guidance), [SAG](https://github.com/ashen-sensored/sd_webui_SAG)
- Image phash and hdash using `imagehash`
- Model merge using `git-rebasin`
- Enable refiner-style workflow for `ldm` backend
@@ -71,6 +64,8 @@ Tech that can be integrated as part of the core workflow...
- [QuickEmbedding](https://github.com/ethansmith2000/QuickEmbedding)
- [DragGAN](https://github.com/XingangPan/DragGAN)
- [LamaCleaner](https://github.com/Sanster/lama-cleaner)
+- [SAG](https://huggingface.co/docs/diffusers/v0.19.3/en/api/pipelines/self_attention_guidance), [SAG](https://github.com/ashen-sensored/sd_webui_SAG)
+- [Localization](https://app.transifex.com/signup/open-source/)
- `TensorRT`
## Random
diff --git a/installer.py b/installer.py
index cd083dde4..bb7d28431 100644
--- a/installer.py
+++ b/installer.py
@@ -18,6 +18,7 @@ class Dot(dict): # dot notation access to dictionary attributes
__delattr__ = dict.__delitem__
+version = None
log = logging.getLogger("sd")
log_file = os.path.join(os.path.dirname(__file__), 'sdnext.log')
log_rolled = False
@@ -177,16 +178,16 @@ def installed(package, friendly: str = None):
spec = pkg_resources.working_set.by_key.get(p[0].replace('_', '-'), None) # check name variations
ok = ok and spec is not None
if ok:
- version = pkg_resources.get_distribution(p[0]).version
- # log.debug(f"Package version found: {p[0]} {version}")
+ package_version = pkg_resources.get_distribution(p[0]).version
+ # log.debug(f"Package version found: {p[0]} {package_version}")
if len(p) > 1:
- exact = version == p[1]
+ exact = package_version == p[1]
ok = ok and (exact or args.experimental)
if not exact:
if args.experimental:
- log.warning(f"Package allowing experimental: {p[0]} {version} required {p[1]}")
+ log.warning(f"Package allowing experimental: {p[0]} {package_version} required {p[1]}")
else:
- log.warning(f"Package wrong version: {p[0]} {version} required {p[1]}")
+ log.warning(f"Package wrong version: {p[0]} {package_version} required {p[1]}")
else:
log.debug(f"Package version not found: {p[0]}")
return ok
@@ -466,8 +467,8 @@ def check_torch():
try:
if args.use_directml and allow_directml:
import torch_directml # pylint: disable=import-error
- version = pkg_resources.get_distribution("torch-directml")
- log.info(f'Torch backend: DirectML ({version})')
+ dml_ver = pkg_resources.get_distribution("torch-directml")
+ log.info(f'Torch backend: DirectML ({dml_ver})')
for i in range(0, torch_directml.device_count()):
log.info(f'Torch detected GPU: {torch_directml.device_name(i)}')
except Exception:
@@ -784,7 +785,7 @@ def check_extensions():
def get_version():
- version = None
+ global version # pylint: disable=global-statement
if version is None:
try:
res = subprocess.run('git log --pretty=format:"%h %ad" -1 --date=short', stdout = subprocess.PIPE, stderr = subprocess.PIPE, shell=True, check=True)
diff --git a/javascript/loader.js b/javascript/loader.js
index f32c7d294..9b8ef4b3e 100644
--- a/javascript/loader.js
+++ b/javascript/loader.js
@@ -31,11 +31,16 @@ async function createSplash() {
const splash = `
`;
document.body.insertAdjacentHTML('beforeend', splash);
await preloadImages();
- const imgElement = ``;
- document.getElementById('splash').insertAdjacentHTML('afterbegin', imgElement);
+ const imgEl = ``;
+ document.getElementById('splash').insertAdjacentHTML('afterbegin', imgEl);
+ fetch('/sdapi/v1/motd')
+ .then((res) => res.text())
+ .then((text) => document.getElementById('motd').innerHTML = text.replace(/["]+/g, ''))
+ .catch((err) => console.error('getMOTD:', err));
}
async function removeSplash() {
diff --git a/javascript/style.css b/javascript/style.css
index 9d9312db6..bc6188003 100644
--- a/javascript/style.css
+++ b/javascript/style.css
@@ -253,6 +253,7 @@ div.controlnet_main_options { display: grid; grid-template-columns: 1fr 1fr; gri
/* loader */
.splash { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; z-index: 1000; display: block; text-align: center; }
+.motd { margin-top: 2em; color: var(--body-text-color-subdued); font-family: monospace; font-variant: all-petite-caps; }
.splash-img { margin: 10% auto 0 auto; width: 512px; background-repeat: no-repeat; height: 512px; animation: color 10s infinite alternate; }
.loading { color: white; position: absolute; top: 20%; left: 50%; transform: translateX(-50%); }
.loader { width: 300px; height: 300px; border: var(--spacing-md) solid transparent; border-radius: 50%; border-top: var(--spacing-md) solid var(--primary-600); animation: spin 4s linear infinite; position: relative; }
diff --git a/modules/api/api.py b/modules/api/api.py
index c70a54176..163e11881 100644
--- a/modules/api/api.py
+++ b/modules/api/api.py
@@ -9,7 +9,7 @@ from fastapi import FastAPI, APIRouter, Depends, Request
from fastapi.security import HTTPBasic, HTTPBasicCredentials
from fastapi.exceptions import HTTPException
from PIL import PngImagePlugin,Image
-
+import requests
import piexif
import piexif.helper
import gradio as gr
@@ -147,6 +147,7 @@ class Api:
self.add_api_route("/sdapi/v1/script-info", self.get_script_info, methods=["GET"], response_model=List[models.ScriptInfo])
self.add_api_route("/sdapi/v1/log", self.get_log_buffer, methods=["GET"], response_model=List) # bypass auth
self.add_api_route("/sdapi/v1/start", self.session_start, methods=["GET"])
+ self.add_api_route("/sdapi/v1/motd", self.get_motd, methods=["GET"], response_model=str)
self.add_api_route("/sdapi/v1/extra-networks", self.get_extra_networks, methods=["GET"], response_model=List[models.ExtraNetworkItem])
self.default_script_arg_txt2img = []
self.default_script_arg_img2img = []
@@ -172,6 +173,19 @@ class Api:
shared.log.info(f'Browser session: client={req.client.host} agent={agent}')
return {}
+ def get_motd(self):
+ from installer import get_version
+ motd = ''
+ ver = get_version()
+ if ver.get('updated', None) is not None:
+ motd = f"version {ver['hash']} {ver['updated']} {ver['url'].split('/')[-1]}
"
+ if shared.opts.motd:
+ res = requests.get('https://vladmandic.github.io/automatic/motd', timeout=10)
+ if res.status_code == 200:
+ shared.log.info(f'MOTD: {res.text}')
+ motd += res.text
+ return motd
+
def get_selectable_script(self, script_name, script_runner):
if script_name is None or script_name == "":
return None, None
diff --git a/modules/middleware.py b/modules/middleware.py
index ead3a3198..e188b4a3d 100644
--- a/modules/middleware.py
+++ b/modules/middleware.py
@@ -26,7 +26,7 @@ def setup_middleware(app: FastAPI, cmd_opts):
from fastapi.middleware.gzip import GZipMiddleware
app.user_middleware = [x for x in app.user_middleware if x.cls.__name__ != 'CORSMiddleware']
app.middleware_stack = None # reset current middleware to allow modifying user provided list
- app.add_middleware(GZipMiddleware, minimum_size=1024)
+ app.add_middleware(GZipMiddleware, minimum_size=2048)
if cmd_opts.cors_origins and cmd_opts.cors_regex:
app.add_middleware(CORSMiddleware, allow_origins=cmd_opts.cors_origins.split(','), allow_origin_regex=cmd_opts.cors_regex, allow_methods=['*'], allow_credentials=True, allow_headers=['*'])
elif cmd_opts.cors_origins:
diff --git a/modules/shared.py b/modules/shared.py
index 656dc9671..970a397f3 100644
--- a/modules/shared.py
+++ b/modules/shared.py
@@ -572,6 +572,7 @@ options_templates.update(options_section(('saving-paths', "Image Naming & Paths"
}))
options_templates.update(options_section(('ui', "User Interface"), {
+ "motd": OptionInfo(True, "Show MOTD"),
"gradio_theme": OptionInfo("black-teal", "UI theme", gr.Dropdown, lambda: {"choices": list_themes()}, refresh=refresh_themes),
"theme_style": OptionInfo("Auto", "Theme mode", gr.Radio, {"choices": ["Auto", "Dark", "Light"]}),
"tooltips": OptionInfo("UI Tooltips", "UI tooltips", gr.Radio, {"choices": ["None", "Browser default", "UI tooltips"], "visible": False}),
diff --git a/motd b/motd
new file mode 100644
index 000000000..0519ecba6
--- /dev/null
+++ b/motd
@@ -0,0 +1 @@
+
\ No newline at end of file