Merge pull request #3102 from ceruleandeep/fix/sdInteractiveYour Fix "send a photo of yourself" etc in SD interactive mode

f6d0f7587c21abee43bfa401ba753e4d2f51e9aa

Cohee <18619528+Cohee1207@users.noreply.github.com>

Signed
1 files changed, +80 -69Ignore whitespace
public/scripts/extensions/stable-diffusion/index.js+80 -69
@@ -1,37 +1,62 @@
11import { Popper } from '../../../lib.js';
22import {
33 saveSettingsDebouncedanimation_duration,
44 systemUserNameappendMediaToMessage,
5- getRequestHeaders,
65 event_types,
76 eventSource,
7+ formatCharacterAvatar,
88 generateQuietPrompt,
99 this_chidgetCharacterAvatar,
1010 getCurrentChatId,
1111 animation_durationgetRequestHeaders,
12- appendMediaToMessage,
1312 getUserAvatar,
1413 user_avatarsaveSettingsDebounced,
15- getCharacterAvatar,
16- formatCharacterAvatar,
1714 substituteParams,
1815 substituteParamsExtended,
16+ systemUserName,
17+ this_chid,
18+ user_avatar,
1919} from '../../../script.js';
20-import { getApiUrl, getContext, extension_settings, doExtrasFetch, modules, renderExtensionTemplateAsync, writeExtensionField } from '../../extensions.js';
20+import {
21+ doExtrasFetch,
22+ extension_settings,
23+ getApiUrl,
24+ getContext,
25+ modules,
26+ renderExtensionTemplateAsync,
27+ writeExtensionField,
28+} from '../../extensions.js';
2129import { selected_group } from '../../group-chats.js';
22-import { stringFormat, initScrollHeight, resetScrollHeight, getCharaFilename, saveBase64AsFile, getBase64Async, delay, isTrueBoolean, debounce, isFalseBoolean, deepMerge } from '../../utils.js';
30+import {
31+ debounce,
32+ deepMerge,
33+ delay,
34+ getBase64Async,
35+ getCharaFilename,
36+ initScrollHeight,
37+ isFalseBoolean,
38+ isTrueBoolean,
39+ resetScrollHeight,
40+ saveBase64AsFile,
41+ stringFormat,
42+} from '../../utils.js';
2343import { getMessageTimeStamp, humanizedDateTime } from '../../RossAscends-mods.js';
2444import { SECRET_KEYS, secret_state, writeSecret } from '../../secrets.js';
2545import { getNovelUnlimitedImageGenerationgetNovelAnlas, getNovelAnlasgetNovelUnlimitedImageGeneration, loadNovelSubscriptionData } from '../../nai-settings.js';
2646import { getMultimodalCaption } from '../shared.js';
2747import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
2848import { SlashCommand } from '../../slash-commands/SlashCommand.js';
29-import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
49+import {
50+ ARGUMENT_TYPE,
51+ SlashCommandArgument,
52+ SlashCommandNamedArgument,
53+} from '../../slash-commands/SlashCommandArgument.js';
3054import { debounce_timeout } from '../../constants.js';
3155import { SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js';
3256import { POPUP_RESULTcallGenericPopup, POPUP_TYPEPopup, PopupPOPUP_RESULT, callGenericPopupPOPUP_TYPE } from '../../popup.js';
3357import { commonEnumProviders } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
3458import { ToolManager } from '../../tool-calling.js';
59+
3560export { MODULE_NAME };
3661
3762const MODULE_NAME = 'sd';
@@ -118,13 +143,13 @@ const triggerWords = {
118143};
119144
120145const messageTrigger = {
121146 activationRegex: /\b(send|mail|imagine|generate|make|create|draw|paint|render|show)\b.{0,10}\b(pic|picture|image|drawing|painting|photo|photograph)\b(?:\s+of)?(?:\s+(?:a|an|the|this|that|those|your)?\s+)?(.+)/i,
122147 specialCases: {
123148 [generationMode.CHARACTER]: ['you', 'yourself'],
124149 [generationMode.USER]: ['me', 'myself'],
125150 [generationMode.SCENARIO]: ['story', 'scenario', 'whole story'],
126151 [generationMode.NOW]: ['last message'],
127152 [generationMode.FACE]: ['your face', 'your portrait', 'your selfie'],
128153 [generationMode.BACKGROUND]: ['background', 'scene background', 'scene', 'scenery', 'surroundings', 'environment'],
129154 },
130155};
@@ -343,7 +368,7 @@ function processTriggers(chat, _, abort) {
343368 return;
344369 }
345370
346371 console.log(`SD: Triggered by "${message}", detected subject: "${subject}"`);
347372
348373 outer: for (const [specialMode, triggers] of Object.entries(messageTrigger.specialCases)) {
349374 for (const trigger of triggers) {
@@ -359,7 +384,6 @@ function processTriggers(chat, _, abort) {
359384 setTimeout(() => generatePicture(initiators.interactive, {}, subject, message), 1);
360385 } catch {
361386 console.log('SD: Failed to process triggers.');
362- return;
363387 }
364388}
365389
@@ -685,7 +709,7 @@ async function refinePrompt(prompt, isNegative) {
685709 return prompt;
686710}
687711
688712async function onChatChanged() {
689713 if (this_chid === undefined || selected_group) {
690714 $('#sd_character_prompt_block').hide();
691715 return;
@@ -713,7 +737,7 @@ function onChatChanged() {
713737 $('#sd_character_prompt').val(characterPrompt);
714738 $('#sd_character_negative_prompt').val(negativePrompt);
715739 $('#sd_character_prompt_share').prop('checked', hasSharedData);
716740 await adjustElementScrollHeight();
717741}
718742
719743async function adjustElementScrollHeight() {
@@ -1285,8 +1309,7 @@ async function getAutoRemoteModel() {
12851309 throw new Error('SD WebUI returned an error.');
12861310 }
12871311
12881312 const data =return await result.text();
1289- return data;
12901313 } catch (error) {
12911314 console.error(error);
12921315 return null;
@@ -1305,9 +1328,7 @@ async function getDrawthingsRemoteModel() {
13051328 throw new Error('SD DrawThings API returned an error.');
13061329 }
13071330
13081331 const data =return await result.text();
1309-
1310- return data;
13111332 } catch (error) {
13121333 console.error(error);
13131334 return null;
@@ -1330,8 +1351,7 @@ async function getAutoRemoteUpscalers() {
13301351 throw new Error('SD WebUI returned an error.');
13311352 }
13321353
13331354 const data =return await result.json();
1334- return data;
13351355 } catch (error) {
13361356 console.error(error);
13371357 return [extension_settings.sd.hr_upscaler];
@@ -1350,8 +1370,7 @@ async function getAutoRemoteSchedulers() {
13501370 throw new Error('SD WebUI returned an error.');
13511371 }
13521372
13531373 const data =return await result.json();
1354- return data;
13551374 } catch (error) {
13561375 console.error(error);
13571376 return ['N/A'];
@@ -1370,8 +1389,7 @@ async function getVladRemoteUpscalers() {
13701389 throw new Error('SD.Next returned an error.');
13711390 }
13721391
13731392 const data =return await result.json();
1374- return data;
13751393 } catch (error) {
13761394 console.error(error);
13771395 return [extension_settings.sd.hr_upscaler];
@@ -1504,8 +1522,7 @@ async function loadHordeSamplers() {
15041522 });
15051523
15061524 if (result.ok) {
15071525 const data =return await result.json();
1508- return data;
15091526 }
15101527
15111528 return [];
@@ -1544,8 +1561,7 @@ async function loadAutoSamplers() {
15441561 throw new Error('SD WebUI returned an error.');
15451562 }
15461563
15471564 const data =return await result.json();
1548- return data;
15491565 } catch (error) {
15501566 return [];
15511567 }
@@ -1583,8 +1599,7 @@ async function loadVladSamplers() {
15831599 throw new Error('SD.Next returned an error.');
15841600 }
15851601
15861602 const data =return await result.json();
1587- return data;
15881603 } catch (error) {
15891604 return [];
15901605 }
@@ -1723,8 +1738,7 @@ async function loadPollinationsModels() {
17231738 });
17241739
17251740 if (result.ok) {
17261741 const data =return await result.json();
1727- return data;
17281742 }
17291743
17301744 return [];
@@ -1742,8 +1756,7 @@ async function loadTogetherAIModels() {
17421756 });
17431757
17441758 if (result.ok) {
17451759 const data =return await result.json();
1746- return data;
17471760 }
17481761
17491762 return [];
@@ -1781,8 +1794,7 @@ async function loadNanoGPTModels() {
17811794 });
17821795
17831796 if (result.ok) {
17841797 const data =return await result.json();
1785- return data;
17861798 }
17871799
17881800 return [];
@@ -1798,8 +1810,10 @@ async function loadHordeModels() {
17981810 if (result.ok) {
17991811 const data = await result.json();
18001812 data.sort((a, b) => b.count - a.count);
1801- const models = data.map(x => ({ value: x.name, text: `${x.name} (ETA: ${x.eta}s, Queue: ${x.queued}, Workers: ${x.count})` }));
1813+ return data.map(x => ({
1802- return models;
1814+ value: x.name,
1815+ text: `${x.name} (ETA: ${x.eta}s, Queue: ${x.queued}, Workers: ${x.count})`,
1816+ }));
18031817 }
18041818
18051819 return [];
@@ -1824,8 +1838,7 @@ async function loadExtrasModels() {
18241838
18251839 if (getModelsResult.ok) {
18261840 const data = await getModelsResult.json();
18271841 const view_models =return data.models.map(x => ({ value: x, text: x }));
1828- return view_models;
18291842 }
18301843
18311844 return [];
@@ -1867,8 +1880,7 @@ async function loadAutoModels() {
18671880 }
18681881 }
18691882
18701883 const data =return await result.json();
1871- return data;
18721884 } catch (error) {
18731885 return [];
18741886 }
@@ -1953,8 +1965,7 @@ async function loadVladModels() {
19531965 }
19541966 }
19551967
19561968 const data =return await result.json();
1957- return data;
19581969 } catch (error) {
19591970 return [];
19601971 }
@@ -2242,7 +2253,7 @@ async function loadComfyWorkflows() {
22422253 $('#sd_comfy_workflow').append(option);
22432254 }
22442255 } catch (error) {
2245- return;
2256+ console.error(`Could not load ComfyUI workflows: ${error.message}`);
22462257 }
22472258}
22482259
@@ -2361,7 +2372,7 @@ function ensureSelectionExists(setting, selector) {
23612372 * @param {string} trigger Subject trigger word
23622373 * @param {string} [message] Chat message
23632374 * @param {function} [callback] Callback function
23642375 * @returns {Promise<string|undefined>} Image path
23652376 */
23662377async function generatePicture(initiator, args, trigger, message, callback) {
23672378 if (!trigger || trigger.trim().length === 0) {
@@ -2379,7 +2390,9 @@ async function generatePicture(initiator, args, trigger, message, callback) {
23792390
23802391 trigger = trigger.trim();
23812392 const generationType = getGenerationType(trigger);
2382- console.log('Generation mode', generationType, 'triggered with', trigger);
2393+ const generationTypeKey = Object.keys(generationMode).find(key => generationMode[key] === generationType);
2394+ console.log(`Generation mode ${generationTypeKey} triggered with "${trigger}"`);
2395+
23832396 const quietPrompt = getQuietPrompt(generationType, trigger);
23842397 const context = getContext();
23852398
@@ -2387,11 +2400,11 @@ async function generatePicture(initiator, args, trigger, message, callback) {
23872400 ? context.groups[Object.keys(context.groups).filter(x => context.groups[x].id === context.groupId)[0]]?.id?.toString()
23882401 : context.characters[context.characterId]?.name;
23892402
23902403 if (generationType === generationMode.BACKGROUND) {
23912404 const callbackOriginal = callback;
23922405 callback = async function (prompt, imagePath, generationType, _negativePromptPrefix, _initiator, prefixedPrompt) {
23932406 const imgUrl = `url("${encodeURI(imagePath)}")`;
23942407 await eventSource.emit(event_types.FORCE_SET_BACKGROUND, { url: imgUrl, path: imagePath });
23952408
23962409 if (typeof callbackOriginal === 'function') {
23972410 await callbackOriginal(prompt, imagePath, generationType, negativePromptPrefix, initiator, prefixedPrompt);
@@ -2446,12 +2459,12 @@ function setTypeSpecificDimensions(generationType) {
24462459 const aspectRatio = extension_settings.sd.width / extension_settings.sd.height;
24472460
24482461 // Face images are always portrait (pun intended)
24492462 if ((generationType === generationMode.FACE || generationType === generationMode.FACE_MULTIMODAL) && aspectRatio >= 1) {
24502463 // Round to nearest multiple of 64
24512464 extension_settings.sd.height = Math.round(extension_settings.sd.width * 1.5 / 64) * 64;
24522465 }
24532466
24542467 if (generationType === generationMode.BACKGROUND) {
24552468 // Background images are always landscape
24562469 if (aspectRatio <= 1) {
24572470 // Round to nearest multiple of 64
@@ -2537,7 +2550,7 @@ async function getPrompt(generationType, message, trigger, quietPrompt, combineN
25372550 */
25382551function generateFreeModePrompt(trigger, combineNegatives) {
25392552 return trigger
25402553 .replace(/(?:^char(\s|,)|\{\{charPrefix\}\})/gi, (_, suffix) => {
25412554 const getLastCharacterKey = () => {
25422555 if (typeof this_chid !== 'undefined') {
25432556 return getCharaFilename(this_chid);
@@ -2545,9 +2558,7 @@ function generateFreeModePrompt(trigger, combineNegatives) {
25452558 const context = getContext();
25462559 for (let i = context.chat.length - 1; i >= 0; i--) {
25472560 const message = context.chat[i];
25482561 if (!message.is_user ||&& !message.is_system && typeof message.original_avatar === 'string') {
2549- continue;
2550- } else if (typeof message.original_avatar === 'string') {
25512562 return message.original_avatar.replace(/\.[^/.]+$/, '');
25522563 }
25532564 }
@@ -2570,11 +2581,11 @@ function generateFreeModePrompt(trigger, combineNegatives) {
25702581async function generateMultimodalPrompt(generationType, quietPrompt) {
25712582 let avatarUrl;
25722583
25732584 if (generationType === generationMode.USER_MULTIMODAL) {
25742585 avatarUrl = getUserAvatarUrl();
25752586 }
25762587
25772588 if (generationType === generationMode.CHARACTER_MULTIMODAL || generationType === generationMode.FACE_MULTIMODAL) {
25782589 avatarUrl = getCharacterAvatarUrl();
25792590 }
25802591
@@ -3182,8 +3193,8 @@ function getNovelParams() {
31823193 const ratio = Math.sqrt(MAX_PIXELS / (width * height));
31833194
31843195 // Calculate new width and height while maintaining aspect ratio.
31853196 varlet newWidth = Math.round(width * ratio);
31863197 varlet newHeight = Math.round(height * ratio);
31873198
31883199 // Ensure new dimensions are multiples of 64. If not, reduce accordingly.
31893200 if (newWidth % 64 !== 0) {
@@ -3479,9 +3490,9 @@ async function onComfyOpenWorkflowEditorClick() {
34793490 const popupResult = popup.show();
34803491 const checkPlaceholders = () => {
34813492 workflow = $('#sd_comfy_workflow_editor_workflow').val().toString();
34823493 $('.sd_comfy_workflow_editor_placeholder_list > li[data-placeholder]').each(function (idx) {
34833494 const key = this.getAttribute('data-placeholder');
34843495 const found = workflow.search(`"%${key}%"`) !== -1;
34853496 this.classList[found ? 'remove' : 'add']('sd_comfy_workflow_editor_not_found');
34863497 });
34873498 };
@@ -3841,7 +3852,7 @@ async function sdMessageButton(e) {
38413852 swipes.push(image);
38423853
38433854 // If already contains an image and it's not inline - leave it as is
38443855 message.extra.inline_image = !(message.extra.image && !message.extra.inline_image ? false : true);
38453856 message.extra.image = image;
38463857 message.extra.title = prompt;
38473858 message.extra.generationType = generationType;