diff --git a/default/config.yaml b/default/config.yaml index 585988686b..a7e7a747e9 100644 --- a/default/config.yaml +++ b/default/config.yaml @@ -118,7 +118,6 @@ extras: classificationModel: Cohee/distilbert-base-uncased-go-emotions-onnx captioningModel: Xenova/vit-gpt2-image-captioning embeddingModel: Cohee/jina-embeddings-v2-base-en - promptExpansionModel: Cohee/fooocus_expansion-onnx speechToTextModel: Xenova/whisper-small textToSpeechModel: Xenova/speecht5_tts # -- OPENAI CONFIGURATION -- diff --git a/public/index.html b/public/index.html index 741871eddf..c6117f665a 100644 --- a/public/index.html +++ b/public/index.html @@ -1709,9 +1709,9 @@
/imagine-source comfy
. Returns the current source.',
+ callback: async (_args, name) => {
+ if (!name) {
+ return extension_settings.sd.source;
+ }
+ const isKnownSource = Object.keys(sources).includes(String(name));
+ if (!isKnownSource) {
+ throw new Error('The value provided is not a valid image generation source.');
+ }
+ const option = document.querySelector(`#sd_source [value="${name}"]`);
+ if (!(option instanceof HTMLOptionElement)) {
+ throw new Error('Could not find the source option in the dropdown.');
+ }
+ option.selected = true;
+ await onSourceChange();
+ return extension_settings.sd.source;
+ },
+ }));
+
+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
+ name: 'imagine-style',
+ aliases: ['sd-style', 'img-style'],
+ returns: 'a name of the current style',
+ unnamedArgumentList: [
+ SlashCommandArgument.fromProps({
+ description: 'style name',
+ typeList: [ARGUMENT_TYPE.STRING],
+ isRequired: false,
+ forceEnum: true,
+ enumProvider: getSelectEnumProvider('sd_style', false),
+ }),
+ ],
+ helpString: 'If an argument is provided, change the style of the image generation, e.g. /imagine-style MyStyle
. Returns the current style.',
+ callback: async (_args, name) => {
+ if (!name) {
+ return extension_settings.sd.style;
+ }
+ const option = document.querySelector(`#sd_style [value="${name}"]`);
+ if (!(option instanceof HTMLOptionElement)) {
+ throw new Error('Could not find the style option in the dropdown.');
+ }
+ option.selected = true;
+ onStyleSelect();
+ return extension_settings.sd.style;
+ },
+ }));
+
SlashCommandParser.addCommandObject(SlashCommand.fromProps({
name: 'imagine-comfy-workflow',
callback: changeComfyWorkflow,
@@ -3832,7 +4101,7 @@ jQuery(async () => {
description: 'workflow name',
typeList: [ARGUMENT_TYPE.STRING],
isRequired: true,
- enumProvider: () => Array.from(document.querySelectorAll('#sd_comfy_workflow > [value]')).map(x => x.getAttribute('value')).map(workflow => new SlashCommandEnumValue(workflow)),
+ enumProvider: getSelectEnumProvider('sd_comfy_workflow', false),
}),
],
helpString: '(workflowName) - change the workflow to be used for image generation with ComfyUI, e.g. /imagine-comfy-workflow MyWorkflow
',
@@ -3874,7 +4143,6 @@ jQuery(async () => {
$('#sd_hr_scale').on('input', onHrScaleInput);
$('#sd_denoising_strength').on('input', onDenoisingStrengthInput);
$('#sd_hr_second_pass_steps').on('input', onHrSecondPassStepsInput);
- $('#sd_novel_upscale_ratio').on('input', onNovelUpscaleRatioInput);
$('#sd_novel_anlas_guard').on('input', onNovelAnlasGuardInput);
$('#sd_novel_view_anlas').on('click', onViewAnlasClick);
$('#sd_novel_sm').on('input', onNovelSmInput);
@@ -3887,7 +4155,6 @@ jQuery(async () => {
$('#sd_comfy_open_workflow_editor').on('click', onComfyOpenWorkflowEditorClick);
$('#sd_comfy_new_workflow').on('click', onComfyNewWorkflowClick);
$('#sd_comfy_delete_workflow').on('click', onComfyDeleteWorkflowClick);
- $('#sd_expand').on('input', onExpandInput);
$('#sd_style').on('change', onStyleSelect);
$('#sd_save_style').on('click', onSaveStyleClick);
$('#sd_delete_style').on('click', onDeleteStyleClick);
diff --git a/public/scripts/extensions/stable-diffusion/settings.html b/public/scripts/extensions/stable-diffusion/settings.html
index f43ed7246d..2efa74d838 100644
--- a/public/scripts/extensions/stable-diffusion/settings.html
+++ b/public/scripts/extensions/stable-diffusion/settings.html
@@ -27,11 +27,6 @@
Extend free mode prompts
(interactive/commands)
-
format
argument to change the output format.',
- returns: 'JSON object of script injections',
+ helpString: 'Lists all script injections for the current chat. Displays injects in a popup by default. Use the return
argument to change the return type.',
+ returns: 'Optionalls the JSON object of script injections',
namedArgumentList: [
+ SlashCommandNamedArgument.fromProps({
+ name: 'return',
+ description: 'The way how you want the return value to be provided',
+ typeList: [ARGUMENT_TYPE.STRING],
+ defaultValue: 'popup-html',
+ enumList: slashCommandReturnHelper.enumList({ allowPipe: false, allowObject: true, allowChat: true, allowPopup: true, allowTextVersion: false }),
+ forceEnum: true,
+ }),
+ // TODO remove some day
SlashCommandNamedArgument.fromProps({
name: 'format',
- description: 'output format',
+ description: '!!! DEPRECATED - use "return" instead !!! output format',
typeList: [ARGUMENT_TYPE.STRING],
isRequired: true,
forceEnum: true,
@@ -1842,37 +1896,43 @@ function injectCallback(args, value) {
}
async function listInjectsCallback(args) {
- const type = String(args?.format).toLowerCase().trim();
- if (!chat_metadata.script_injects || !Object.keys(chat_metadata.script_injects).length) {
- type !== 'none' && toastr.info('No script injections for the current chat');
- return JSON.stringify({});
- }
-
- const injects = Object.entries(chat_metadata.script_injects)
- .map(([id, inject]) => {
- const position = Object.entries(extension_prompt_types);
- const positionName = position.find(([_, value]) => value === inject.position)?.[0] ?? 'unknown';
- return `* **${id}**: ${inject.value}
(${positionName}, depth: ${inject.depth}, scan: ${inject.scan ?? false}, role: ${inject.role ?? extension_prompt_roles.SYSTEM})`;
- })
- .join('\n');
-
- const converter = new showdown.Converter();
- const messageText = `### Script injections:\n${injects}`;
- const htmlMessage = DOMPurify.sanitize(converter.makeHtml(messageText));
-
- switch (type) {
- case 'none':
- break;
- case 'chat':
- sendSystemMessage(system_message_types.GENERIC, htmlMessage);
- break;
- case 'popup':
- default:
- await callGenericPopup(htmlMessage, POPUP_TYPE.TEXT);
- break;
+ /** @type {import('./slash-commands/SlashCommandReturnHelper.js').SlashCommandReturnType} */
+ let returnType = args.return;
+
+ // Old legacy return type handling
+ if (args.format) {
+ toastr.warning(`Legacy argument 'format' with value '${args.format}' is deprecated. Please use 'return' instead. Routing to the correct return type...`, 'Deprecation warning');
+ const type = String(args?.format).toLowerCase().trim();
+ if (!chat_metadata.script_injects || !Object.keys(chat_metadata.script_injects).length) {
+ type !== 'none' && toastr.info('No script injections for the current chat');
+ }
+ switch (type) {
+ case 'none':
+ returnType = 'none';
+ break;
+ case 'chat':
+ returnType = 'chat-html';
+ break;
+ case 'popup':
+ default:
+ returnType = 'popup-html';
+ break;
+ }
}
- return JSON.stringify(chat_metadata.script_injects);
+ // Now the actual new return type handling
+ const buildTextValue = (injects) => {
+ const injectsStr = Object.entries(injects)
+ .map(([id, inject]) => {
+ const position = Object.entries(extension_prompt_types);
+ const positionName = position.find(([_, value]) => value === inject.position)?.[0] ?? 'unknown';
+ return `* **${id}**: ${inject.value}
(${positionName}, depth: ${inject.depth}, scan: ${inject.scan ?? false}, role: ${inject.role ?? extension_prompt_roles.SYSTEM})`;
+ })
+ .join('\n');
+ return `### Script injections:\n${injectsStr || 'No script injections for the current chat'}`;
+ };
+
+ return await slashCommandReturnHelper.doReturn(returnType ?? 'popup-html', chat_metadata.script_injects ?? {}, { objectToStringFunc: buildTextValue });
}
/**
@@ -2559,7 +2619,7 @@ async function askCharacter(args, text) {
// Not supported in group chats
// TODO: Maybe support group chats?
if (selected_group) {
- toastr.error('Cannot run /ask command in a group chat!');
+ toastr.warning('Cannot run /ask command in a group chat!');
return '';
}
@@ -2633,7 +2693,9 @@ async function askCharacter(args, text) {
}
}
- return askResult;
+ const message = askResult ? chat[chat.length - 1] : null;
+
+ return await slashCommandReturnHelper.doReturn(args.return ?? 'pipe', message, { objectToStringFunc: x => x.mes });
}
async function hideMessageCallback(_, arg) {
@@ -2908,7 +2970,7 @@ function findPersonaByName(name) {
async function sendUserMessageCallback(args, text) {
if (!text) {
- console.warn('WARN: No text provided for /send command');
+ toastr.warning('You must specify text to send');
return;
}
@@ -2924,16 +2986,17 @@ async function sendUserMessageCallback(args, text) {
insertAt = chat.length + insertAt;
}
+ let message;
if ('name' in args) {
const name = args.name || '';
const avatar = findPersonaByName(name) || user_avatar;
- await sendMessageAsUser(text, bias, insertAt, compact, name, avatar);
+ message = await sendMessageAsUser(text, bias, insertAt, compact, name, avatar);
}
else {
- await sendMessageAsUser(text, bias, insertAt, compact);
+ message = await sendMessageAsUser(text, bias, insertAt, compact);
}
- return '';
+ return await slashCommandReturnHelper.doReturn(args.return ?? 'none', message, { objectToStringFunc: x => x.mes });
}
async function deleteMessagesByNameCallback(_, name) {
@@ -3221,30 +3284,20 @@ export function getNameAndAvatarForMessage(character, name = null) {
export async function sendMessageAs(args, text) {
if (!text) {
+ toastr.warning('You must specify text to send as');
return '';
}
- let name;
+ let name = args.name?.trim();
let mesText;
- if (args.name) {
- name = args.name.trim();
-
- if (!name && !text) {
- toastr.warning('You must specify a name and text to send as');
- return '';
- }
- } else {
+ if (!name) {
const namelessWarningKey = 'sendAsNamelessWarningShown';
if (localStorage.getItem(namelessWarningKey) !== 'true') {
toastr.warning('To avoid confusion, please use /sendas name="Character Name"', 'Name defaulted to {{char}}', { timeOut: 10000 });
localStorage.setItem(namelessWarningKey, 'true');
}
name = name2;
- if (!text) {
- toastr.warning('You must specify text to send as');
- return '';
- }
}
mesText = text.trim();
@@ -3321,11 +3374,12 @@ export async function sendMessageAs(args, text) {
await saveChatConditional();
}
- return '';
+ return await slashCommandReturnHelper.doReturn(args.return ?? 'none', message, { objectToStringFunc: x => x.mes });
}
export async function sendNarratorMessage(args, text) {
if (!text) {
+ toastr.warning('You must specify text to send');
return '';
}
@@ -3374,7 +3428,7 @@ export async function sendNarratorMessage(args, text) {
await saveChatConditional();
}
- return '';
+ return await slashCommandReturnHelper.doReturn(args.return ?? 'none', message, { objectToStringFunc: x => x.mes });
}
export async function promptQuietForLoudResponse(who, text) {
@@ -3420,6 +3474,7 @@ export async function promptQuietForLoudResponse(who, text) {
async function sendCommentMessage(args, text) {
if (!text) {
+ toastr.warning('You must specify text to send');
return '';
}
@@ -3462,7 +3517,7 @@ async function sendCommentMessage(args, text) {
await saveChatConditional();
}
- return '';
+ return await slashCommandReturnHelper.doReturn(args.return ?? 'none', message, { objectToStringFunc: x => x.mes });
}
/**
diff --git a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js
index 5a40965c13..b96b83a53b 100644
--- a/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js
+++ b/public/scripts/slash-commands/SlashCommandCommonEnumsProvider.js
@@ -36,6 +36,7 @@ export const enumIcons = {
message: 'đŦ',
voice: 'đ¤',
server: 'đĨī¸',
+ popup: 'đ',
true: 'âī¸',
false: 'â',
diff --git a/public/scripts/slash-commands/SlashCommandReturnHelper.js b/public/scripts/slash-commands/SlashCommandReturnHelper.js
new file mode 100644
index 0000000000..3601c30cd1
--- /dev/null
+++ b/public/scripts/slash-commands/SlashCommandReturnHelper.js
@@ -0,0 +1,80 @@
+import { sendSystemMessage, system_message_types } from '../../script.js';
+import { callGenericPopup, POPUP_TYPE } from '../popup.js';
+import { escapeHtml } from '../utils.js';
+import { enumIcons } from './SlashCommandCommonEnumsProvider.js';
+import { enumTypes, SlashCommandEnumValue } from './SlashCommandEnumValue.js';
+
+/** @typedef {'pipe'|'object'|'chat-html'|'chat-text'|'popup-html'|'popup-text'|'toast-html'|'toast-text'|'console'|'none'} SlashCommandReturnType */
+
+export const slashCommandReturnHelper = {
+ // Without this, VSCode formatter fucks up JS docs. Don't ask me why.
+ _: false,
+
+ /**
+ * Gets/creates the enum list of types of return relevant for a slash command
+ *
+ * @param {object} [options={}] Options
+ * @param {boolean} [options.allowPipe=true] Allow option to pipe the return value
+ * @param {boolean} [options.allowObject=false] Allow option to return the value as an object
+ * @param {boolean} [options.allowChat=false] Allow option to return the value as a chat message
+ * @param {boolean} [options.allowPopup=false] Allow option to return the value as a popup
+ * @param {boolean}[options.allowTextVersion=true] Used in combination with chat/popup/toast, some of them do not make sense for text versions, e.g.if you are building a HTML string anyway
+ * @returns {SlashCommandEnumValue[]} The enum list
+ */
+ enumList: ({ allowPipe = true, allowObject = false, allowChat = false, allowPopup = false, allowTextVersion = true } = {}) => [
+ allowPipe && new SlashCommandEnumValue('pipe', 'Return to the pipe for the next command', enumTypes.name, '|'),
+ allowObject && new SlashCommandEnumValue('object', 'Return as an object (or array) to the pipe for the next command', enumTypes.variable, enumIcons.dictionary),
+ allowChat && new SlashCommandEnumValue('chat-html', 'Sending a chat message with the return value - Can display HTML', enumTypes.command, enumIcons.message),
+ allowChat && allowTextVersion && new SlashCommandEnumValue('chat-text', 'Sending a chat message with the return value - Will only display as text', enumTypes.qr, enumIcons.message),
+ allowPopup && new SlashCommandEnumValue('popup-html', 'Showing as a popup with the return value - Can display HTML', enumTypes.command, enumIcons.popup),
+ allowPopup && allowTextVersion && new SlashCommandEnumValue('popup-text', 'Showing as a popup with the return value - Will only display as text', enumTypes.qr, enumIcons.popup),
+ new SlashCommandEnumValue('toast-html', 'Show the return value as a toast notification - Can display HTML', enumTypes.command, 'âšī¸'),
+ allowTextVersion && new SlashCommandEnumValue('toast-text', 'Show the return value as a toast notification - Will only display as text', enumTypes.qr, 'âšī¸'),
+ new SlashCommandEnumValue('console', 'Log the return value (object, if it can be one) to the console', enumTypes.enum, '>'),
+ new SlashCommandEnumValue('none', 'No return value'),
+ ].filter(x => !!x),
+
+ /**
+ * Handles the return value based on the specified type
+ *
+ * @param {SlashCommandReturnType} type The type of return
+ * @param {object|number|string} value The value to return
+ * @param {object} [options={}] Options
+ * @param {(o: object) => string} [options.objectToStringFunc=null] Function to convert the object to a string, if object was provided and 'object' was not the chosen return type
+ * @param {(o: object) => string} [options.objectToHtmlFunc=null] Analog to 'objectToStringFunc', which will be used here if not provided - but can do a different string layout if HTML is requested
+ * @returns {Promise<*>} The processed return value
+ */
+ async doReturn(type, value, { objectToStringFunc = o => o?.toString(), objectToHtmlFunc = null } = {}) {
+ const shouldHtml = type.endsWith('html');
+ const actualConverterFunc = shouldHtml && objectToHtmlFunc ? objectToHtmlFunc : objectToStringFunc;
+ const stringValue = typeof value !== 'string' ? actualConverterFunc(value) : value;
+
+ switch (type) {
+ case 'popup-html':
+ case 'popup-text':
+ case 'chat-text':
+ case 'chat-html':
+ case 'toast-text':
+ case 'toast-html': {
+ const htmlOrNotHtml = shouldHtml ? DOMPurify.sanitize((new showdown.Converter()).makeHtml(stringValue)) : escapeHtml(stringValue);
+
+ if (type.startsWith('popup')) await callGenericPopup(htmlOrNotHtml, POPUP_TYPE.TEXT);
+ if (type.startsWith('chat')) sendSystemMessage(system_message_types.GENERIC, htmlOrNotHtml);
+ if (type.startsWith('toast')) toastr.info(htmlOrNotHtml, null, { escapeHtml: !shouldHtml });
+
+ return '';
+ }
+ case 'pipe':
+ return stringValue ?? '';
+ case 'object':
+ return JSON.stringify(value);
+ case 'console':
+ console.info(value);
+ return '';
+ case 'none':
+ return '';
+ default:
+ throw new Error(`Unknown return type: ${type}`);
+ }
+ },
+};
diff --git a/public/scripts/variables.js b/public/scripts/variables.js
index 7c9830a365..c768c4f5e8 100644
--- a/public/scripts/variables.js
+++ b/public/scripts/variables.js
@@ -11,6 +11,7 @@ import { SlashCommandClosureResult } from './slash-commands/SlashCommandClosureR
import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
import { SlashCommandEnumValue, enumTypes } from './slash-commands/SlashCommandEnumValue.js';
import { PARSER_FLAG, SlashCommandParser } from './slash-commands/SlashCommandParser.js';
+import { slashCommandReturnHelper } from './slash-commands/SlashCommandReturnHelper.js';
import { SlashCommandScope } from './slash-commands/SlashCommandScope.js';
import { isFalseBoolean, convertValueType, isTrueBoolean } from './utils.js';
@@ -305,7 +306,28 @@ export function replaceVariableMacros(input) {
}
async function listVariablesCallback(args) {
- const type = String(args?.format || '').toLowerCase().trim() || 'popup';
+ /** @type {import('./slash-commands/SlashCommandReturnHelper.js').SlashCommandReturnType} */
+ let returnType = args.return;
+
+ // Old legacy return type handling
+ if (args.format) {
+ toastr.warning(`Legacy argument 'format' with value '${args.format}' is deprecated. Please use 'return' instead. Routing to the correct return type...`, 'Deprecation warning');
+ const type = String(args?.format).toLowerCase().trim();
+ switch (type) {
+ case 'none':
+ returnType = 'none';
+ break;
+ case 'chat':
+ returnType = 'chat-html';
+ break;
+ case 'popup':
+ default:
+ returnType = 'popup-html';
+ break;
+ }
+ }
+
+ // Now the actual new return type handling
const scope = String(args?.scope || '').toLowerCase().trim() || 'all';
if (!chat_metadata.variables) {
chat_metadata.variables = {};
@@ -317,35 +339,24 @@ async function listVariablesCallback(args) {
const localVariables = includeLocalVariables ? Object.entries(chat_metadata.variables).map(([name, value]) => `${name}: ${value}`) : [];
const globalVariables = includeGlobalVariables ? Object.entries(extension_settings.variables.global).map(([name, value]) => `${name}: ${value}`) : [];
+ const buildTextValue = (_) => {
+ const localVariablesString = localVariables.length > 0 ? localVariables.join('\n\n') : 'No local variables';
+ const globalVariablesString = globalVariables.length > 0 ? globalVariables.join('\n\n') : 'No global variables';
+ const chatName = getCurrentChatId();
+
+ const message = [
+ includeLocalVariables ? `### Local variables (${chatName}):\n${localVariablesString}` : '',
+ includeGlobalVariables ? `### Global variables:\n${globalVariablesString}` : '',
+ ].filter(x => x).join('\n\n');
+ return message;
+ };
+
const jsonVariables = [
...Object.entries(chat_metadata.variables).map(x => ({ key: x[0], value: x[1], scope: 'local' })),
...Object.entries(extension_settings.variables.global).map(x => ({ key: x[0], value: x[1], scope: 'global' })),
];
- const localVariablesString = localVariables.length > 0 ? localVariables.join('\n\n') : 'No local variables';
- const globalVariablesString = globalVariables.length > 0 ? globalVariables.join('\n\n') : 'No global variables';
- const chatName = getCurrentChatId();
-
- const converter = new showdown.Converter();
- const message = [
- includeLocalVariables ? `### Local variables (${chatName}):\n${localVariablesString}` : '',
- includeGlobalVariables ? `### Global variables:\n${globalVariablesString}` : '',
- ].filter(x => x).join('\n\n');
- const htmlMessage = DOMPurify.sanitize(converter.makeHtml(message));
-
- switch (type) {
- case 'none':
- break;
- case 'chat':
- sendSystemMessage(system_message_types.GENERIC, htmlMessage);
- break;
- case 'popup':
- default:
- await callGenericPopup(htmlMessage, POPUP_TYPE.TEXT);
- break;
- }
-
- return JSON.stringify(jsonVariables);
+ return await slashCommandReturnHelper.doReturn(returnType ?? 'popup-html', jsonVariables, { objectToStringFunc: buildTextValue });
}
/**
@@ -916,7 +927,7 @@ export function registerVariableCommands() {
name: 'listvar',
callback: listVariablesCallback,
aliases: ['listchatvar'],
- helpString: 'List registered chat variables. Displays variables in a popup by default. Use the format
argument to change the output format.',
+ helpString: 'List registered chat variables. Displays variables in a popup by default. Use the return
argument to change the return type.',
returns: 'JSON list of local variables',
namedArgumentList: [
SlashCommandNamedArgument.fromProps({
@@ -932,9 +943,18 @@ export function registerVariableCommands() {
new SlashCommandEnumValue('global', 'Global variables', enumTypes.enum, enumIcons.globalVariable),
],
}),
+ SlashCommandNamedArgument.fromProps({
+ name: 'return',
+ description: 'The way how you want the return value to be provided',
+ typeList: [ARGUMENT_TYPE.STRING],
+ defaultValue: 'popup-html',
+ enumList: slashCommandReturnHelper.enumList({ allowPipe: false, allowObject: true, allowChat: true, allowPopup: true, allowTextVersion: false }),
+ forceEnum: true,
+ }),
+ // TODO remove some day
SlashCommandNamedArgument.fromProps({
name: 'format',
- description: 'output format',
+ description: '!!! DEPRECATED - use "return" instead !!! output format',
typeList: [ARGUMENT_TYPE.STRING],
isRequired: true,
forceEnum: true,
diff --git a/public/style.css b/public/style.css
index 7d55cf8325..01a49ab9f7 100644
--- a/public/style.css
+++ b/public/style.css
@@ -969,34 +969,53 @@ body .panelControlBar {
/* SWIPE RELATED STYLES*/
+.mes {
+ --swipeCounterHeight: 15px;
+ --swipeCounterMargin: 5px;
+}
+
.swipe_right,
.swipe_left {
- height: 40px;
- width: 40px;
+ width: 25px;
+ height: 25px;
opacity: 0.3;
align-items: center;
justify-content: center;
z-index: 9999;
grid-row-start: 2;
- font-size: 30px;
+ font-size: 20px;
cursor: pointer;
align-self: center;
+}
+
+.swipe_left {
position: absolute;
-bottom: 15px;
-flex-flow: column;
+ bottom: calc(var(--swipeCounterHeight) + var(--swipeCounterMargin));
+ flex-flow: column;
}
+.swipeRightBlock {
+ position: absolute;
+ right: 0;
+ bottom: 0;
+}
.swipes-counter {
color: var(--SmartThemeBodyColor);
font-size: 12px;
- padding: 0;
+ padding: 0 5px;
font-family: var(--mainFontFamily);
font-weight: 400;
align-self: center;
min-width: 40px;
display: flex;
justify-content: center;
+ margin-bottom: var(--swipeCounterMargin);
+ height: var(--swipeCounterHeight);
+}
+
+.mes:not(.last_mes) .swipes-counter {
+ opacity: 0.3;
}
.swipe_left {
@@ -1006,7 +1025,7 @@ flex-flow: column;
.swipe_right {
right: 5px;
- align-self:end;
+ align-self: center;
}
.ui-settings {
@@ -2640,7 +2659,7 @@ select option:not(:checked) {
#instruct_enabled_label .menu_button:not(.toggleEnabled),
#sysprompt_enabled_label .menu_button:not(.toggleEnabled) {
- color: Red;
+ color: Red;
}
.displayBlock {
diff --git a/src/endpoints/stable-diffusion.js b/src/endpoints/stable-diffusion.js
index 9eff948f19..b6348b8b2f 100644
--- a/src/endpoints/stable-diffusion.js
+++ b/src/endpoints/stable-diffusion.js
@@ -9,41 +9,6 @@ const { jsonParser } = require('../express-common');
const { readSecret, SECRET_KEYS } = require('./secrets.js');
const FormData = require('form-data');
-/**
- * Sanitizes a string.
- * @param {string} x String to sanitize
- * @returns {string} Sanitized string
- */
-function safeStr(x) {
- x = String(x);
- x = x.replace(/ +/g, ' ');
- x = x.trim();
- x = x.replace(/^[\s,.]+|[\s,.]+$/g, '');
- return x;
-}
-
-const splitStrings = [
- ', extremely',
- ', intricate,',
-];
-
-const dangerousPatterns = '[]ãã()īŧīŧ|:īŧ';
-
-/**
- * Removes patterns from a string.
- * @param {string} x String to sanitize
- * @param {string} pattern Pattern to remove
- * @returns {string} Sanitized string
- */
-function removePattern(x, pattern) {
- for (let i = 0; i < pattern.length; i++) {
- let p = pattern[i];
- let regex = new RegExp('\\' + p, 'g');
- x = x.replace(regex, '');
- }
- return x;
-}
-
/**
* Gets the comfy workflows.
* @param {import('../users.js').UserDirectoryList} directories
@@ -391,40 +356,6 @@ router.post('/sd-next/upscalers', jsonParser, async (request, response) => {
}
});
-/**
- * SD prompt expansion using GPT-2 text generation model.
- * Adapted from: https://github.com/lllyasviel/Fooocus/blob/main/modules/expansion.py
- */
-router.post('/expand', jsonParser, async (request, response) => {
- const originalPrompt = request.body.prompt;
-
- if (!originalPrompt) {
- console.warn('No prompt provided for SD expansion.');
- return response.send({ prompt: '' });
- }
-
- console.log('Refine prompt input:', originalPrompt);
- const splitString = splitStrings[Math.floor(Math.random() * splitStrings.length)];
- let prompt = safeStr(originalPrompt) + splitString;
-
- try {
- const task = 'text-generation';
- const module = await import('../transformers.mjs');
- const pipe = await module.default.getPipeline(task);
-
- const result = await pipe(prompt, { num_beams: 1, max_new_tokens: 256, do_sample: true });
-
- const newText = result[0].generated_text;
- const newPrompt = safeStr(removePattern(newText, dangerousPatterns));
- console.log('Refine prompt output:', newPrompt);
-
- return response.send({ prompt: newPrompt });
- } catch {
- console.warn('Failed to load transformers.js pipeline.');
- return response.send({ prompt: originalPrompt });
- }
-});
-
const comfy = express.Router();
comfy.post('/ping', jsonParser, async (request, response) => {
diff --git a/src/transformers.mjs b/src/transformers.mjs
index fe947123a5..09714e3bb1 100644
--- a/src/transformers.mjs
+++ b/src/transformers.mjs
@@ -31,12 +31,6 @@ const tasks = {
configField: 'extras.embeddingModel',
quantized: true,
},
- 'text-generation': {
- defaultModel: 'Cohee/fooocus_expansion-onnx',
- pipeline: null,
- configField: 'extras.promptExpansionModel',
- quantized: false,
- },
'automatic-speech-recognition': {
defaultModel: 'Xenova/whisper-small',
pipeline: null,