mirror of
https://github.com/easydiffusion/easydiffusion.git
synced 2025-02-23 13:51:51 +01:00
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:
parent
bae0bec1cc
commit
e287df1320
@ -266,6 +266,7 @@ async function init() {
|
|||||||
await getAppConfig()
|
await getAppConfig()
|
||||||
await getModels()
|
await getModels()
|
||||||
await initSettings()
|
await initSettings()
|
||||||
|
await loadUIPlugins()
|
||||||
|
|
||||||
setInterval(healthCheck, HEALTH_PING_INTERVAL * 1000)
|
setInterval(healthCheck, HEALTH_PING_INTERVAL * 1000)
|
||||||
healthCheck()
|
healthCheck()
|
||||||
|
@ -369,7 +369,7 @@ function showImages(reqBody, res, outputContainer, livePreview) {
|
|||||||
let buttons = [
|
let buttons = [
|
||||||
{ text: 'Use as Input', on_click: onUseAsInputClick },
|
{ text: 'Use as Input', on_click: onUseAsInputClick },
|
||||||
{ text: 'Download', on_click: onDownloadImageClick },
|
{ text: 'Download', on_click: onDownloadImageClick },
|
||||||
{ text: 'Make Similar Images', on_click: onMakeSimilarClick },
|
{ text: 'Make Similar Images', on_click: onMakeSimilarClick }
|
||||||
]
|
]
|
||||||
|
|
||||||
// include the plugins
|
// include the plugins
|
||||||
@ -423,56 +423,6 @@ function onDownloadImageClick(req, img) {
|
|||||||
imgDownload.click()
|
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) {
|
function onMakeSimilarClick(req, img) {
|
||||||
let newTaskRequest = getCurrentUserRequest()
|
let newTaskRequest = getCurrentUserRequest()
|
||||||
|
|
||||||
|
@ -27,53 +27,21 @@ const PLUGINS = {
|
|||||||
IMAGE_INFO_BUTTONS: []
|
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') })
|
console.log('loading plugin', pluginPath)
|
||||||
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 })
|
|
||||||
|
|
||||||
function getStartNewTaskHandler(mode) {
|
document.head.appendChild(script)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
newTaskRequest.seed = newTaskRequest.reqBody.seed
|
} catch (e) {
|
||||||
newTaskRequest.numOutputsTotal = 1
|
console.log('error fetching plugin paths', e)
|
||||||
newTaskRequest.batchCount = 1
|
|
||||||
createTask(newTaskRequest)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
17
ui/server.py
17
ui/server.py
@ -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'))
|
CONFIG_DIR = os.path.abspath(os.path.join(SD_UI_DIR, '..', 'scripts'))
|
||||||
MODELS_DIR = os.path.abspath(os.path.join(SD_DIR, '..', 'models'))
|
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
|
OUTPUT_DIRNAME = "Stable Diffusion UI" # in the user's home folder
|
||||||
TASK_TTL = 15 * 60 # Discard last session's task timeout
|
TASK_TTL = 15 * 60 # Discard last session's task timeout
|
||||||
@ -31,11 +32,15 @@ app = FastAPI()
|
|||||||
modifiers_cache = None
|
modifiers_cache = None
|
||||||
outpath = os.path.join(os.path.expanduser("~"), OUTPUT_DIRNAME)
|
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
|
# don't show access log entries for URLs that start with the given prefix
|
||||||
ACCESS_LOG_SUPPRESS_PATH_PREFIXES = ['/ping', '/image', '/modifier-thumbnails']
|
ACCESS_LOG_SUPPRESS_PATH_PREFIXES = ['/ping', '/image', '/modifier-thumbnails']
|
||||||
|
|
||||||
NOCACHE_HEADERS={"Cache-Control": "no-cache, no-store, must-revalidate", "Pragma": "no-cache", "Expires": "0"}
|
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):
|
class SetAppConfigRequest(BaseModel):
|
||||||
update_branch: str = "main"
|
update_branch: str = "main"
|
||||||
@ -251,6 +256,15 @@ def getModels():
|
|||||||
|
|
||||||
return models
|
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}')
|
@app.get('/get/{key:path}')
|
||||||
def read_web_data(key:str=None):
|
def read_web_data(key:str=None):
|
||||||
if not key: # /get without parameters, stable-diffusion easter egg.
|
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)
|
return JSONResponse(getModels(), headers=NOCACHE_HEADERS)
|
||||||
elif key == 'modifiers': return FileResponse(os.path.join(SD_UI_DIR, 'modifiers.json'), 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 == 'output_dir': return JSONResponse({ 'output_dir': outpath }, headers=NOCACHE_HEADERS)
|
||||||
|
elif key == 'ui_plugins': return JSONResponse(getUIPlugins(), headers=NOCACHE_HEADERS)
|
||||||
else:
|
else:
|
||||||
raise HTTPException(status_code=404, detail=f'Request for unknown {key}') # HTTP404 Not Found
|
raise HTTPException(status_code=404, detail=f'Request for unknown {key}') # HTTP404 Not Found
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user