Allow loading UI plugins from a /plugins/ URL path, which loads files ending with .plugin.js inside the plugins/ui folder

This commit is contained in:
cmdr2 2022-10-19 21:34:40 +05:30
parent bae0bec1cc
commit e287df1320
4 changed files with 31 additions and 97 deletions

View File

@ -266,6 +266,7 @@ async function init() {
await getAppConfig()
await getModels()
await initSettings()
await loadUIPlugins()
setInterval(healthCheck, HEALTH_PING_INTERVAL * 1000)
healthCheck()

View File

@ -369,7 +369,7 @@ function showImages(reqBody, res, outputContainer, livePreview) {
let buttons = [
{ text: 'Use as Input', on_click: onUseAsInputClick },
{ text: 'Download', on_click: onDownloadImageClick },
{ text: 'Make Similar Images', on_click: onMakeSimilarClick },
{ text: 'Make Similar Images', on_click: onMakeSimilarClick }
]
// include the plugins
@ -423,56 +423,6 @@ function onDownloadImageClick(req, img) {
imgDownload.click()
}
function getStartNewTaskHandler(mode) {
return function(reqBody, img) {
if (!isServerAvailable()) {
alert('The server is not available.')
return
}
const newTaskRequest = getCurrentUserRequest()
switch (mode) {
case 'img2img':
case 'img2img_X2':
newTaskRequest.reqBody = Object.assign({}, reqBody, {
num_outputs: 1,
use_cpu: useCPUField.checked,
})
if (!newTaskRequest.reqBody.init_image || mode === 'img2img_X2') {
newTaskRequest.reqBody.sampler = 'ddim'
newTaskRequest.reqBody.prompt_strength = '0.5'
newTaskRequest.reqBody.init_image = img.src
delete newTaskRequest.reqBody.mask
} else {
newTaskRequest.reqBody.seed = 1 + newTaskRequest.reqBody.seed
}
if (mode === 'img2img_X2') {
newTaskRequest.reqBody.width = reqBody.width * 2
newTaskRequest.reqBody.height = reqBody.height * 2
newTaskRequest.reqBody.num_inference_steps = Math.min(100, reqBody.num_inference_steps * 2)
if (useUpscalingField.checked) {
newTaskRequest.reqBody.use_upscale = upscaleModelField.value
} else {
delete newTaskRequest.reqBody.use_upscale
}
}
break
case 'upscale':
newTaskRequest.reqBody = Object.assign({}, reqBody, {
num_outputs: 1,
//use_face_correction: 'GFPGANv1.3',
use_upscale: upscaleModelField.value,
})
break
default:
throw new Error("Unknown upscale mode: " + mode)
}
newTaskRequest.seed = newTaskRequest.reqBody.seed
newTaskRequest.numOutputsTotal = 1
newTaskRequest.batchCount = 1
createTask(newTaskRequest)
}
}
function onMakeSimilarClick(req, img) {
let newTaskRequest = getCurrentUserRequest()

View File

@ -27,53 +27,21 @@ const PLUGINS = {
IMAGE_INFO_BUTTONS: []
}
async function loadUIPlugins() {
try {
let res = await fetch('/get/ui_plugins')
if (res.status === 200) {
res = await res.json()
res.forEach(pluginPath => {
let script = document.createElement('script')
script.src = pluginPath
PLUGINS['IMAGE_INFO_BUTTONS'].push({ text: 'Double Size', on_click: getStartNewTaskHandler('img2img_X2') })
PLUGINS['IMAGE_INFO_BUTTONS'].push({ text: 'Redo', on_click: getStartNewTaskHandler('img2img') })
PLUGINS['IMAGE_INFO_BUTTONS'].push({ text: 'Upscale', on_click: getStartNewTaskHandler('upscale'), filter: (req, img) => !req.use_upscale })
console.log('loading plugin', pluginPath)
function getStartNewTaskHandler(mode) {
return function(reqBody, img) {
const newTaskRequest = getCurrentUserRequest()
switch (mode) {
case 'img2img':
case 'img2img_X2':
newTaskRequest.reqBody = Object.assign({}, reqBody, {
num_outputs: 1,
use_cpu: useCPUField.checked,
})
if (!newTaskRequest.reqBody.init_image || mode === 'img2img_X2') {
newTaskRequest.reqBody.sampler = 'ddim'
newTaskRequest.reqBody.prompt_strength = '0.5'
newTaskRequest.reqBody.init_image = img.src
delete newTaskRequest.reqBody.mask
} else {
newTaskRequest.reqBody.seed = 1 + newTaskRequest.reqBody.seed
}
if (mode === 'img2img_X2') {
newTaskRequest.reqBody.width = reqBody.width * 2
newTaskRequest.reqBody.height = reqBody.height * 2
newTaskRequest.reqBody.num_inference_steps = Math.min(100, reqBody.num_inference_steps * 2)
if (useUpscalingField.checked) {
newTaskRequest.reqBody.use_upscale = upscaleModelField.value
} else {
delete newTaskRequest.reqBody.use_upscale
}
}
break
case 'upscale':
newTaskRequest.reqBody = Object.assign({}, reqBody, {
num_outputs: 1,
//use_face_correction: 'GFPGANv1.3',
use_upscale: upscaleModelField.value,
})
break
default:
throw new Error("Unknown upscale mode: " + mode)
document.head.appendChild(script)
})
}
newTaskRequest.seed = newTaskRequest.reqBody.seed
newTaskRequest.numOutputsTotal = 1
newTaskRequest.batchCount = 1
createTask(newTaskRequest)
} catch (e) {
console.log('error fetching plugin paths', e)
}
}

View File

@ -12,6 +12,7 @@ sys.path.append(os.path.dirname(SD_UI_DIR))
CONFIG_DIR = os.path.abspath(os.path.join(SD_UI_DIR, '..', 'scripts'))
MODELS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'models'))
UI_PLUGINS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'plugins', 'ui'))
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
TASK_TTL = 15 * 60 # Discard last session's task timeout
@ -31,11 +32,15 @@ app = FastAPI()
modifiers_cache = None
outpath = os.path.join(os.path.expanduser("~"), OUTPUT_DIRNAME)
os.makedirs(UI_PLUGINS_DIR, exist_ok=True)
# don't show access log entries for URLs that start with the given prefix
ACCESS_LOG_SUPPRESS_PATH_PREFIXES = ['/ping', '/image', '/modifier-thumbnails']
NOCACHE_HEADERS={"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'media/')), name="media")
app.mount('/media', StaticFiles(directory=os.path.join(SD_UI_DIR, 'media')), name="media")
app.mount('/plugins', StaticFiles(directory=UI_PLUGINS_DIR), name="plugins")
class SetAppConfigRequest(BaseModel):
update_branch: str = "main"
@ -251,6 +256,15 @@ def getModels():
return models
def getUIPlugins():
plugins = []
for file in os.listdir(UI_PLUGINS_DIR):
if file.endswith('.plugin.js'):
plugins.append(f'/plugins/{file}')
return plugins
@app.get('/get/{key:path}')
def read_web_data(key:str=None):
if not key: # /get without parameters, stable-diffusion easter egg.
@ -264,6 +278,7 @@ def read_web_data(key:str=None):
return JSONResponse(getModels(), headers=NOCACHE_HEADERS)
elif key == 'modifiers': return FileResponse(os.path.join(SD_UI_DIR, 'modifiers.json'), headers=NOCACHE_HEADERS)
elif key == 'output_dir': return JSONResponse({ 'output_dir': outpath }, headers=NOCACHE_HEADERS)
elif key == 'ui_plugins': return JSONResponse(getUIPlugins(), headers=NOCACHE_HEADERS)
else:
raise HTTPException(status_code=404, detail=f'Request for unknown {key}') # HTTP404 Not Found