|
|
@@ -25,6 +25,19 @@ const credentialTypes = [
|
|
|
|
|
|
const configSchema = {
|
|
|
type: 'object',
|
|
|
+ // Offered as a button in the editor. Pressing it asks the server what it
|
|
|
+ // has loaded and writes those values into the settings below, where they
|
|
|
+ // can then be changed. It fills the form in; it does not decide anything at
|
|
|
+ // run time, so what the workflow will do stays visible on the node.
|
|
|
+ prefill: {
|
|
|
+ label: 'Take from the server',
|
|
|
+ description: 'Fill these in from the model the server currently has loaded',
|
|
|
+ node: 'sdcpp-health',
|
|
|
+ needs: ['serverUrl'],
|
|
|
+ map: {
|
|
|
+ modelName: 'modelName'
|
|
|
+ }
|
|
|
+ },
|
|
|
properties: {
|
|
|
serverUrl: {
|
|
|
type: 'string', title: 'Server URL',
|
|
|
@@ -36,30 +49,15 @@ const configSchema = {
|
|
|
description: 'A basic credential holding the sdcpp-restapi username and password. Listing models needs one',
|
|
|
dynamicOptions: { source: 'credentials', filter: { type: ['sdcpp', 'basic'] } }
|
|
|
},
|
|
|
- source: {
|
|
|
- type: 'string', title: 'Model',
|
|
|
- enum: ['choose', 'loaded'],
|
|
|
- enumLabels: ['Pick one from the server', 'Whatever is loaded right now'],
|
|
|
- default: 'choose',
|
|
|
- description: 'Pick one, or take the model the server currently has loaded. Taking the loaded one keeps a workflow portable between servers, and means it never spends minutes swapping a model just to match what a node was set to'
|
|
|
- },
|
|
|
- includeComponents: {
|
|
|
- type: 'boolean', title: 'Include Components',
|
|
|
- default: false,
|
|
|
- showWhen: { field: 'source', value: 'loaded' },
|
|
|
- description: 'Also supply the VAE, CLIP, T5, LLM and TAESD the server has loaded, not only the model name. Only useful for a diffusion model, which loads its parts separately'
|
|
|
- },
|
|
|
modelType: {
|
|
|
type: 'string', title: 'Kind',
|
|
|
- showWhen: { field: 'source', value: 'choose' },
|
|
|
enum: ['checkpoint', 'diffusion', 'vae', 'lora', 'clip', 't5', 'embedding',
|
|
|
'controlnet', 'llm', 'esrgan', 'taesd', 'motion_module', 'adetailer'],
|
|
|
default: 'checkpoint',
|
|
|
description: 'Which kind of model to choose from. esrgan is the upscaler kind'
|
|
|
},
|
|
|
modelName: {
|
|
|
- type: 'string', title: 'Choose',
|
|
|
- showWhen: { field: 'source', value: 'choose' },
|
|
|
+ type: 'string', title: 'Model',
|
|
|
description: 'Chosen from what the server has. Change the Kind above to list a different sort',
|
|
|
dynamicOptions: {
|
|
|
source: 'node',
|
|
|
@@ -88,8 +86,6 @@ const outputSchema = {
|
|
|
_config: { type: 'object', description: 'The setting this supplies, as the engine consumes it' },
|
|
|
modelName: { type: 'string', description: 'The chosen model' },
|
|
|
modelType: { type: 'string' },
|
|
|
- architecture: { type: 'string', description: 'What the server detected, when following the loaded model' },
|
|
|
- loadedComponents: { type: 'object', description: 'The components the server has loaded, when following it' },
|
|
|
setting: { type: 'string', description: 'Which setting it was supplied as' },
|
|
|
models: { type: 'array', description: 'Everything of this kind the server has. Only filled when listing' }
|
|
|
}
|
|
|
@@ -286,45 +282,14 @@ async function execute(config, input, context) {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- let modelName;
|
|
|
- let architecture = '';
|
|
|
- let loadedComponents = {};
|
|
|
- const values = {};
|
|
|
-
|
|
|
- if ((config.source || 'choose') === 'loaded') {
|
|
|
- // /health is unauthenticated, so this works before any credential is
|
|
|
- // set up - useful when the point is to follow whatever the server has.
|
|
|
- const health = readHealth(server, Math.min(timeout, 15000));
|
|
|
- if (health.model_loaded !== true || !health.model_name) {
|
|
|
- throw new Error('SD.cpp Model: this node is set to use the model the server has ' +
|
|
|
- 'loaded, but ' + server + ' has none. Load one first, or choose a model here');
|
|
|
- }
|
|
|
- modelName = health.model_name;
|
|
|
- architecture = health.model_architecture || '';
|
|
|
- loadedComponents = health.loaded_components || {};
|
|
|
-
|
|
|
- if (config.includeComponents === true) {
|
|
|
- for (let i = 0; i < COMPONENT_SETTINGS.length; i++) {
|
|
|
- const entry = COMPONENT_SETTINGS[i];
|
|
|
- for (let k = 0; k < entry.keys.length; k++) {
|
|
|
- const found = loadedComponents[entry.keys[k]];
|
|
|
- // A component the server does not have comes back empty or
|
|
|
- // absent; supplying that would blank the target's own value.
|
|
|
- if (found) {
|
|
|
- values[entry.setting] = found;
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } else {
|
|
|
- modelName = String(config.modelName || '').trim();
|
|
|
- if (!modelName) {
|
|
|
- throw new Error('SD.cpp Model: choose a model. Pick one from the list, which is read ' +
|
|
|
- 'from the server named above');
|
|
|
- }
|
|
|
+ const modelName = String(config.modelName || '').trim();
|
|
|
+ if (!modelName) {
|
|
|
+ throw new Error('SD.cpp Model: choose a model. Pick one from the list, which is read ' +
|
|
|
+ 'from the server named above');
|
|
|
}
|
|
|
|
|
|
+ const values = {};
|
|
|
+
|
|
|
const setting = String(config.setting || '').trim() ||
|
|
|
SETTING_FOR_KIND[modelType] || 'modelName';
|
|
|
|
|
|
@@ -338,8 +303,6 @@ async function execute(config, input, context) {
|
|
|
_config: values,
|
|
|
modelName: modelName,
|
|
|
modelType: modelType,
|
|
|
- architecture: architecture,
|
|
|
- loadedComponents: loadedComponents,
|
|
|
setting: setting,
|
|
|
models: []
|
|
|
};
|