CC/PM: Add generation type trigger prompt filter (#4281) * CC/PM: Add generation type trigger prompt filter Closes #4276 * Fix element cast type * Narrower element types * Change trigger to multiple select * Extract class scope function * Fix control name * Add 'enabled' property to Prompt class and update type annotations in PromptManager methods * Clarify placeholder of multiselect

d9f4028952f1eadf6dfb322c87bb0de96bcf244e

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

Signed
7 files changed, +291 -107Showing whitespace changes
public/css/promptmanager.css+4 -0
@@ -112,6 +112,10 @@
112 flex-direction: column;112 flex-direction: column;
113}113}
114114
115.completion_prompt_manager_popup_entry_form .select2-container {
116 margin: 5px 0;
117}
118
115#completion_prompt_manager_popup .completion_prompt_manager_popup_entry_form_control:has(#completion_prompt_manager_popup_entry_form_prompt) {119#completion_prompt_manager_popup .completion_prompt_manager_popup_entry_form_control:has(#completion_prompt_manager_popup_entry_form_prompt) {
116 flex: 1;120 flex: 1;
117 display: flex;121 display: flex;
public/index.html+16 -0
@@ -6720,6 +6720,22 @@
6720 </select>6720 </select>
6721 <div class="text_muted" data-i18n="To whom this message will be attributed.">To whom this message will be attributed.</div>6721 <div class="text_muted" data-i18n="To whom this message will be attributed.">To whom this message will be attributed.</div>
6722 </div>6722 </div>
6723 <div class="completion_prompt_manager_popup_entry_form_control flex1">
6724 <label for="completion_prompt_manager_popup_entry_form_injection_trigger">
6725 <span data-i18n="Triggers">Triggers</span>
6726 </label>
6727 <select id="completion_prompt_manager_popup_entry_form_injection_trigger" class="text_pole" name="injection_trigger" multiple>
6728 <option data-i18n="Normal" value="normal">Normal</option>
6729 <option data-i18n="Continue" value="continue">Continue</option>
6730 <option data-i18n="Impersonate" value="impersonate">Impersonate</option>
6731 <option data-i18n="Swipe" value="swipe">Swipe</option>
6732 <option data-i18n="Regenerate" value="regenerate">Regenerate</option>
6733 <option data-i18n="Quiet" value="quiet">Quiet</option>
6734 </select>
6735 <div class="text_muted" data-i18n="Filter to specific generation types.">
6736 Filter to specific generation types.
6737 </div>
6738 </div>
6723 </div>6739 </div>
6724 <div class="flex-container gap10px">6740 <div class="flex-container gap10px">
6725 <div class="completion_prompt_manager_popup_entry_form_control flex1">6741 <div class="completion_prompt_manager_popup_entry_form_control flex1">
public/script.js+0 -2
@@ -3540,7 +3540,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
3540 'impersonate',3540 'impersonate',
3541 'quiet',3541 'quiet',
3542 'continue',3542 'continue',
3543 'ask_command',
3544 ];3543 ];
3545 //for normal messages sent from user..3544 //for normal messages sent from user..
3546 if ((textareaText != '' || (hasPendingFileAttachment() && !noAttachTypes.includes(type))) && !automatic_trigger && type !== 'quiet' && !dryRun) {3545 if ((textareaText != '' || (hasPendingFileAttachment() && !noAttachTypes.includes(type))) && !automatic_trigger && type !== 'quiet' && !dryRun) {
@@ -4380,7 +4379,6 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
4380 cyclePrompt: cyclePrompt,4379 cyclePrompt: cyclePrompt,
4381 systemPromptOverride: system,4380 systemPromptOverride: system,
4382 jailbreakPromptOverride: jailbreak,4381 jailbreakPromptOverride: jailbreak,
4383 personaDescription: persona,
4384 messages: oaiMessages,4382 messages: oaiMessages,
4385 messageExamples: oaiMessageExamples,4383 messageExamples: oaiMessageExamples,
4386 }, dryRun);4384 }, dryRun);
public/scripts/PromptManager.js+258 -95
@@ -6,7 +6,7 @@ import { event_types, eventSource, is_send_press, main_api, substituteParams } f
6import { is_group_generating } from './group-chats.js';6import { is_group_generating } from './group-chats.js';
7import { Message, MessageCollection, TokenHandler } from './openai.js';7import { Message, MessageCollection, TokenHandler } from './openai.js';
8import { power_user } from './power-user.js';8import { power_user } from './power-user.js';
9import { debounce, waitUntilCondition, escapeHtml } from './utils.js';9import { debounce, waitUntilCondition, escapeHtml, uuidv4 } from './utils.js';
10import { debounce_timeout } from './constants.js';10import { debounce_timeout } from './constants.js';
11import { renderTemplateAsync } from './templates.js';11import { renderTemplateAsync } from './templates.js';
12import { Popup } from './popup.js';12import { Popup } from './popup.js';
@@ -29,6 +29,7 @@ function debouncePromise(func, delay) {
29}29}
3030
31const DEFAULT_DEPTH = 4;31const DEFAULT_DEPTH = 4;
32const DEFAULT_ORDER = 100;
3233
33/**34/**
34 * @enum {number}35 * @enum {number}
@@ -77,25 +78,108 @@ const registerPromptManagerMigration = () => {
77 * Represents a prompt.78 * Represents a prompt.
78 */79 */
79class Prompt {80class Prompt {
80 identifier; role; content; name; system_prompt; position; injection_position; injection_depth; injection_order; forbid_overrides; extension;81 /**
82 * Indicates if the prompt is enabled.
83 * @type {boolean}
84 */
85 enabled;
86
87 /**
88 * Unique identifier for the prompt.
89 * @type {string}
90 */
91 identifier;
92
93 /**
94 * Role of the prompt, e.g., 'system', 'user', etc.
95 * @type {string}
96 */
97 role;
98
99 /**
100 * Content of the prompt.
101 * @type {string}
102 */
103 content;
104
105 /**
106 * Display name of the prompt.
107 * @type {string}
108 */
109 name;
110
111 /**
112 * Indicates if the prompt is a system prompt.
113 * @type {boolean}
114 */
115 system_prompt;
116
117 /**
118 * Position of the prompt in the prompt list.
119 * @type {string|number}
120 */
121 position;
122
123 /**
124 * Inject position of the prompt (relative = 0 or in-chat = 1)
125 * @type {number}
126 */
127 injection_position;
128
129 /**
130 * Depth of the prompt in the chat.
131 * @type {number}
132 */
133 injection_depth;
134
135 /**
136 * Order of the prompt in the chat.
137 * @type {number}
138 */
139 injection_order;
140
141 /**
142 * Indicates if the prompt should not be overridden.
143 * @type {boolean}
144 */
145 forbid_overrides;
146
147 /**
148 * Prompt is added by an extension.
149 * @type {boolean}
150 */
151 extension;
152
153 /**
154 * A list of generation type triggers for the prompt injection.
155 * @type {string[]}
156 */
157 injection_trigger;
158
159 /**
160 * Indicates if the prompt is a marker prompt.
161 * @type {boolean}
162 */
163 marker;
81164
82 /**165 /**
83 * Create a new Prompt instance.166 * Create a new Prompt instance.
84 *167 *
85 * @param {Object} param0 - Object containing the properties of the prompt.168 * @param {Object} [param0] - Object containing the properties of the prompt.
86 * @param {string} param0.identifier - The unique identifier of the prompt.169 * @param {string} [param0.identifier] - The unique identifier of the prompt.
87 * @param {string} param0.role - The role associated with the prompt.170 * @param {string} [param0.role] - The role associated with the prompt.
88 * @param {string} param0.content - The content of the prompt.171 * @param {string} [param0.content] - The content of the prompt.
89 * @param {string} [param0.name] - The name of the prompt.172 * @param {string} [param0.name] - The name of the prompt.
90 * @param {boolean} [param0.system_prompt] - Indicates if the prompt is a system prompt.173 * @param {boolean} [param0.system_prompt] - Indicates if the prompt is a system prompt.
91 * @param {string} [param0.position] - The position of the prompt in the prompt list.174 * @param {string|number} [param0.position] - The position of the prompt in the prompt list.
92 * @param {number} [param0.injection_position] - The insert position of the prompt.175 * @param {number} [param0.injection_position] - The insert position of the prompt.
93 * @param {number} [param0.injection_depth] - The depth of the prompt in the chat.176 * @param {number} [param0.injection_depth] - The depth of the prompt in the chat.
94 * @param {number} [param0.injection_order] - The order of the prompt in the chat.177 * @param {number} [param0.injection_order] - The order of the prompt in the chat.
178 * @param {string[]} [param0.injection_trigger] - The generation type trigger for the prompt injection.
95 * @param {boolean} [param0.forbid_overrides] - Indicates if the prompt should not be overridden.179 * @param {boolean} [param0.forbid_overrides] - Indicates if the prompt should not be overridden.
96 * @param {boolean} [param0.extension] - Prompt is added by an extension.180 * @param {boolean} [param0.extension] - Prompt is added by an extension.
97 */181 */
98 constructor({ identifier, role, content, name, system_prompt, position, injection_depth, injection_position, forbid_overrides, extension, injection_order } = {}) {182 constructor({ identifier, role, content, name, system_prompt, position, injection_depth, injection_position, forbid_overrides, extension, injection_order, injection_trigger } = {}) {
99 this.identifier = identifier;183 this.identifier = identifier;
100 this.role = role;184 this.role = role;
101 this.content = content;185 this.content = content;
@@ -106,7 +190,8 @@ class Prompt {
106 this.injection_position = injection_position;190 this.injection_position = injection_position;
107 this.forbid_overrides = forbid_overrides;191 this.forbid_overrides = forbid_overrides;
108 this.extension = extension ?? false;192 this.extension = extension ?? false;
109 this.injection_order = injection_order ?? 100;193 this.injection_order = injection_order ?? DEFAULT_ORDER;
194 this.injection_trigger = injection_trigger ?? [];
110 }195 }
111}196}
112197
@@ -114,7 +199,16 @@ class Prompt {
114 * Representing a collection of prompts.199 * Representing a collection of prompts.
115 */200 */
116export class PromptCollection {201export class PromptCollection {
202 /**
203 * List of Prompts in the collection.
204 * @type {Prompt[]}
205 */
117 collection = [];206 collection = [];
207
208 /**
209 * List of identifiers of prompts that have been overridden.
210 * @type {string[]}
211 */
118 overriddenPrompts = [];212 overriddenPrompts = [];
119213
120 /**214 /**
@@ -129,7 +223,7 @@ export class PromptCollection {
129 /**223 /**
130 * Checks if the provided instances are of the Prompt class.224 * Checks if the provided instances are of the Prompt class.
131 *225 *
132 * @param {...any} prompts - Instances to check.226 * @param {...Prompt} prompts - Instances to check.
133 * @throws Will throw an error if one or more instances are not of the Prompt class.227 * @throws Will throw an error if one or more instances are not of the Prompt class.
134 */228 */
135 checkPromptInstance(...prompts) {229 checkPromptInstance(...prompts) {
@@ -191,6 +285,12 @@ export class PromptCollection {
191 return this.index(identifier) !== -1;285 return this.index(identifier) !== -1;
192 }286 }
193287
288 /**
289 * Overrides a prompt at a specific position in the collection.
290 *
291 * @param {Prompt} prompt - The Prompt instance to override.
292 * @param {number} position - The position in the collection to override the Prompt instance.
293 */
194 override(prompt, position) {294 override(prompt, position) {
195 this.set(prompt, position);295 this.set(prompt, position);
196 this.overriddenPrompts.push(prompt.identifier);296 this.overriddenPrompts.push(prompt.identifier);
@@ -274,7 +374,7 @@ class PromptManager {
274 this.tryGenerate = async () => { };374 this.tryGenerate = async () => { };
275375
276 /** Called to persist the configuration, must return a promise */376 /** Called to persist the configuration, must return a promise */
277 this.saveServiceSettings = () => { };377 this.saveServiceSettings = () => { return Promise.resolve(); };
278378
279 /** Toggle prompt button click */379 /** Toggle prompt button click */
280 this.handleToggle = () => { };380 this.handleToggle = () => { };
@@ -444,32 +544,51 @@ class PromptManager {
444 break;544 break;
445 }545 }
446546
447 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name').value = prompt.name;547 const nameField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name'));
448 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role').value = 'system';548 const roleField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role'));
449 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt').value = prompt.content ?? '';549 const promptField = /** @type {HTMLTextAreaElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt'));
450 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position').value = prompt.injection_position ?? 0;550 const injectionPositionField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position'));
451 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth').value = prompt.injection_depth ?? DEFAULT_DEPTH;551 const injectionDepthField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth'));
452 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_order').value = prompt.injection_order ?? 100;552 const injectionOrderField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_order'));
453 document.getElementById(this.configuration.prefix + 'prompt_manager_depth_block').style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';553 const injectionTriggerField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_trigger'));
454 document.getElementById(this.configuration.prefix + 'prompt_manager_order_block').style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';554 const depthBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_depth_block'));
455 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides').checked = prompt.forbid_overrides ?? false;555 const orderBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_order_block'));
456 document.getElementById(this.configuration.prefix + 'prompt_manager_forbid_overrides_block').style.visibility = this.overridablePrompts.includes(prompt.identifier) ? 'visible' : 'hidden';556 const forbidOverridesField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides'));
457 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt').disabled = prompt.marker ?? false;557 const forbidOverridesBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_forbid_overrides_block'));
458 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source_block').style.display = isPulledPrompt ? '' : 'none';558 const entrySourceBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source_block'));
559 const entrySource = /** @type {HTMLSpanElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source'));
560
561 nameField.value = prompt.name;
562 roleField.value = 'system';
563 promptField.value = prompt.content ?? '';
564 injectionPositionField.value = (prompt.injection_position ?? 0).toString();
565 injectionDepthField.value = (prompt.injection_depth ?? DEFAULT_DEPTH).toString();
566 injectionOrderField.value = (prompt.injection_order ?? DEFAULT_ORDER).toString();
567 Array.from(injectionTriggerField.options).forEach(option => {
568 option.selected = false;
569 });
570 injectionTriggerField.dispatchEvent(new Event('change', { bubbles: true }));
571 depthBlock.style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';
572 orderBlock.style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';
573 forbidOverridesField.checked = prompt.forbid_overrides ?? false;
574 forbidOverridesBlock.style.visibility = this.overridablePrompts.includes(prompt.identifier) ? 'visible' : 'hidden';
575 promptField.disabled = prompt.marker ?? false;
576 entrySourceBlock.style.display = isPulledPrompt ? '' : 'none';
459577
460 if (isPulledPrompt) {578 if (isPulledPrompt) {
461 const sourceName = this.promptSources[promptId];579 const sourceName = this.promptSources[promptId];
462 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source').textContent = sourceName;580 entrySource.textContent = sourceName;
463 }581 }
464582
465 if (!this.systemPrompts.includes(promptId)) {583 if (!this.systemPrompts.includes(promptId)) {
466 document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position').removeAttribute('disabled');584 injectionPositionField.removeAttribute('disabled');
467 }585 }
468 };586 };
469587
470 // Append prompt to selected character588 // Append prompt to selected character
471 this.handleAppendPrompt = (event) => {589 this.handleAppendPrompt = (event) => {
472 const promptID = document.getElementById(this.configuration.prefix + 'prompt_manager_footer_append_prompt').value;590 const appendPromptFooter = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_footer_append_prompt'));
591 const promptID = appendPromptFooter.value;
473 const prompt = this.getPromptById(promptID);592 const prompt = this.getPromptById(promptID);
474593
475 if (prompt) {594 if (prompt) {
@@ -483,7 +602,8 @@ class PromptManager {
483 this.handleDeletePrompt = async (event) => {602 this.handleDeletePrompt = async (event) => {
484 Popup.show.confirm(t`Are you sure you want to delete this prompt?`, null).then((userChoice) => {603 Popup.show.confirm(t`Are you sure you want to delete this prompt?`, null).then((userChoice) => {
485 if (!userChoice) return;604 if (!userChoice) return;
486 const promptID = document.getElementById(this.configuration.prefix + 'prompt_manager_footer_append_prompt').value;605 const appendPromptFooter = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_footer_append_prompt'));
606 const promptID = appendPromptFooter.value;
487 const prompt = this.getPromptById(promptID);607 const prompt = this.getPromptById(promptID);
488608
489 if (prompt && true === this.isPromptDeletionAllowed(prompt)) {609 if (prompt && true === this.isPromptDeletionAllowed(prompt)) {
@@ -566,6 +686,7 @@ class PromptManager {
566 fileOpener.accept = '.json';686 fileOpener.accept = '.json';
567687
568 fileOpener.addEventListener('change', (event) => {688 fileOpener.addEventListener('change', (event) => {
689 if (!(event.target instanceof HTMLInputElement)) return;
569 const file = event.target.files[0];690 const file = event.target.files[0];
570 if (!file) return;691 if (!file) return;
571692
@@ -575,7 +696,7 @@ class PromptManager {
575 const fileContent = event.target.result;696 const fileContent = event.target.result;
576697
577 try {698 try {
578 const data = JSON.parse(fileContent);699 const data = JSON.parse(fileContent.toString());
579 this.import(data);700 this.import(data);
580 } catch (err) {701 } catch (err) {
581 toastr.error(t`An error occurred while importing prompts. More info available in console.`);702 toastr.error(t`An error occurred while importing prompts. More info available in console.`);
@@ -615,7 +736,7 @@ class PromptManager {
615736
616 // Update edit form if present737 // Update edit form if present
617 // @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent738 // @see https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetParent
618 const popupEditFormPrompt = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt');739 const popupEditFormPrompt = /** @type {HTMLTextAreaElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt'));
619 if (popupEditFormPrompt.offsetParent) {740 if (popupEditFormPrompt.offsetParent) {
620 popupEditFormPrompt.value = prompt.content;741 popupEditFormPrompt.value = prompt.content;
621 }742 }
@@ -673,6 +794,7 @@ class PromptManager {
673794
674 // Trigger re-render when token settings are changed795 // Trigger re-render when token settings are changed
675 document.getElementById('openai_max_context').addEventListener('change', (event) => {796 document.getElementById('openai_max_context').addEventListener('change', (event) => {
797 if (!(event.target instanceof HTMLInputElement)) return;
676 this.serviceSettings.openai_max_context = event.target.value;798 this.serviceSettings.openai_max_context = event.target.value;
677 if (this.activeCharacter) this.renderDebounced();799 if (this.activeCharacter) this.renderDebounced();
678 });800 });
@@ -778,23 +900,33 @@ class PromptManager {
778900
779 /**901 /**
780 * Update a prompt with the values from the HTML form.902 * Update a prompt with the values from the HTML form.
781 * @param {object} prompt - The prompt to be updated.903 * @param {Partial<Prompt>} prompt - The prompt to be updated.
782 * @returns {void}904 * @returns {void}
783 */905 */
784 updatePromptWithPromptEditForm(prompt) {906 updatePromptWithPromptEditForm(prompt) {
785 prompt.name = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name').value;907 const nameField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name'));
786 prompt.role = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role').value;908 const roleField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role'));
787 prompt.content = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt').value;909 const promptField = /** @type {HTMLTextAreaElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt'));
788 prompt.injection_position = Number(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position').value);910 const injectionPositionField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position'));
789 prompt.injection_depth = Number(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth').value);911 const injectionDepthField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth'));
790 prompt.injection_order = Number(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_order').value);912 const injectionOrderField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_order'));
791 prompt.forbid_overrides = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides').checked;913 const injectionTriggerField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_trigger'));
914 const forbidOverridesField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides'));
915
916 prompt.name = nameField.value;
917 prompt.role = roleField.value;
918 prompt.content = promptField.value;
919 prompt.injection_position = Number(injectionPositionField.value);
920 prompt.injection_depth = Number(injectionDepthField.value);
921 prompt.injection_order = Number(injectionOrderField.value);
922 prompt.injection_trigger = Array.from(injectionTriggerField.selectedOptions).map(option => option.value);
923 prompt.forbid_overrides = forbidOverridesField.checked;
792 }924 }
793925
794 /**926 /**
795 * Find a prompt by its identifier and update it with the provided object.927 * Find a prompt by its identifier and update it with the provided object.
796 * @param {string} identifier - The identifier of the prompt.928 * @param {string} identifier - The identifier of the prompt.
797 * @param {object} updatePrompt - An object with properties to be updated in the prompt.929 * @param {Prompt} updatePrompt - An object with properties to be updated in the prompt.
798 * @returns {void}930 * @returns {void}
799 */931 */
800 updatePromptByIdentifier(identifier, updatePrompt) {932 updatePromptByIdentifier(identifier, updatePrompt) {
@@ -804,7 +936,7 @@ class PromptManager {
804936
805 /**937 /**
806 * Iterate over an array of prompts, find each one by its identifier, and update them with the provided data.938 * Iterate over an array of prompts, find each one by its identifier, and update them with the provided data.
807 * @param {object[]} prompts - An array of prompt updates.939 * @param {Prompt[]} prompts - An array of prompt updates.
808 * @returns {void}940 * @returns {void}
809 */941 */
810 updatePrompts(prompts) {942 updatePrompts(prompts) {
@@ -826,7 +958,7 @@ class PromptManager {
826958
827 /**959 /**
828 * Add a prompt to the current character's prompt list.960 * Add a prompt to the current character's prompt list.
829 * @param {object} prompt - The prompt to be added.961 * @param {Prompt} prompt - The prompt to be added.
830 * @param {object} character - The character whose prompt list will be updated.962 * @param {object} character - The character whose prompt list will be updated.
831 * @returns {void}963 * @returns {void}
832 */964 */
@@ -839,7 +971,7 @@ class PromptManager {
839971
840 /**972 /**
841 * Remove a prompt from the current character's prompt list.973 * Remove a prompt from the current character's prompt list.
842 * @param {object} prompt - The prompt to be removed.974 * @param {Prompt} prompt - The prompt to be removed.
843 * @param {object} character - The character whose prompt list will be updated.975 * @param {object} character - The character whose prompt list will be updated.
844 * @returns {void}976 * @returns {void}
845 */977 */
@@ -853,7 +985,7 @@ class PromptManager {
853985
854 /**986 /**
855 * Create a new prompt and add it to the list of prompts.987 * Create a new prompt and add it to the list of prompts.
856 * @param {object} prompt - The prompt to be added.988 * @param {Partial<Prompt>} prompt - The prompt to be added.
857 * @param {string} identifier - The identifier for the new prompt.989 * @param {string} identifier - The identifier for the new prompt.
858 * @returns {void}990 * @returns {void}
859 */991 */
@@ -931,7 +1063,7 @@ class PromptManager {
9311063
932 /**1064 /**
933 * Check whether a prompt can be inspected.1065 * Check whether a prompt can be inspected.
934 * @param {object} prompt - The prompt to check.1066 * @param {Prompt} prompt - The prompt to check.
935 * @returns {boolean} True if the prompt is a marker, false otherwise.1067 * @returns {boolean} True if the prompt is a marker, false otherwise.
936 */1068 */
937 isPromptInspectionAllowed(prompt) {1069 isPromptInspectionAllowed(prompt) {
@@ -940,7 +1072,7 @@ class PromptManager {
9401072
941 /**1073 /**
942 * Check whether a prompt can be deleted. System prompts cannot be deleted.1074 * Check whether a prompt can be deleted. System prompts cannot be deleted.
943 * @param {object} prompt - The prompt to check.1075 * @param {Prompt} prompt - The prompt to check.
944 * @returns {boolean} True if the prompt can be deleted, false otherwise.1076 * @returns {boolean} True if the prompt can be deleted, false otherwise.
945 */1077 */
946 isPromptDeletionAllowed(prompt) {1078 isPromptDeletionAllowed(prompt) {
@@ -949,7 +1081,7 @@ class PromptManager {
9491081
950 /**1082 /**
951 * Check whether a prompt can be edited.1083 * Check whether a prompt can be edited.
952 * @param {object} prompt - The prompt to check.1084 * @param {Prompt} prompt - The prompt to check.
953 * @returns {boolean} True if the prompt can be edited, false otherwise.1085 * @returns {boolean} True if the prompt can be edited, false otherwise.
954 */1086 */
955 isPromptEditAllowed(prompt) {1087 isPromptEditAllowed(prompt) {
@@ -966,7 +1098,7 @@ class PromptManager {
9661098
967 /**1099 /**
968 * Check whether a prompt can be toggled on or off.1100 * Check whether a prompt can be toggled on or off.
969 * @param {object} prompt - The prompt to check.1101 * @param {Prompt} prompt - The prompt to check.
970 * @returns {boolean} True if the prompt can be deleted, false otherwise.1102 * @returns {boolean} True if the prompt can be deleted, false otherwise.
971 */1103 */
972 isPromptToggleAllowed(prompt) {1104 isPromptToggleAllowed(prompt) {
@@ -1062,7 +1194,7 @@ class PromptManager {
10621194
1063 /**1195 /**
1064 * Get the prompts for a specific character. Can be filtered to only include enabled prompts.1196 * Get the prompts for a specific character. Can be filtered to only include enabled prompts.
1065 * @returns {object[]} The prompts for the character.1197 * @returns {Prompt[]} The prompts for the character.
1066 * @param character1198 * @param character
1067 * @param onlyEnabled1199 * @param onlyEnabled
1068 */1200 */
@@ -1075,7 +1207,7 @@ class PromptManager {
1075 /**1207 /**
1076 * Get the order of prompts for a specific character. If no character is specified or the character doesn't have a prompt list, an empty array is returned.1208 * Get the order of prompts for a specific character. If no character is specified or the character doesn't have a prompt list, an empty array is returned.
1077 * @param {object|null} character - The character to get the prompt list for.1209 * @param {object|null} character - The character to get the prompt list for.
1078 * @returns {object[]} The prompt list for the character, or an empty array.1210 * @returns {Partial<Prompt>[]} The prompt list for the character, or an empty array.
1079 */1211 */
1080 getPromptOrderForCharacter(character) {1212 getPromptOrderForCharacter(character) {
1081 return !character ? [] : (this.serviceSettings.prompt_order.find(list => String(list.character_id) === String(character.id))?.order ?? []);1213 return !character ? [] : (this.serviceSettings.prompt_order.find(list => String(list.character_id) === String(character.id))?.order ?? []);
@@ -1083,7 +1215,7 @@ class PromptManager {
10831215
1084 /**1216 /**
1085 * Set the prompts for the manager.1217 * Set the prompts for the manager.
1086 * @param {object[]} prompts - The prompts to be set.1218 * @param {Partial<Prompt>[]} prompts - The prompts to be set.
1087 * @returns {void}1219 * @returns {void}
1088 */1220 */
1089 setPrompts(prompts) {1221 setPrompts(prompts) {
@@ -1125,7 +1257,7 @@ class PromptManager {
1125 /**1257 /**
1126 * Finds and returns a prompt by its identifier.1258 * Finds and returns a prompt by its identifier.
1127 * @param {string} identifier - Identifier of the prompt1259 * @param {string} identifier - Identifier of the prompt
1128 * @returns {Object|null} The prompt object, or null if not found1260 * @returns {Prompt|null} The prompt object, or null if not found
1129 */1261 */
1130 getPromptById(identifier) {1262 getPromptById(identifier) {
1131 return this.serviceSettings.prompts.find(item => item && item.identifier === identifier) ?? null;1263 return this.serviceSettings.prompts.find(item => item && item.identifier === identifier) ?? null;
@@ -1143,9 +1275,9 @@ class PromptManager {
1143 /**1275 /**
1144 * Enriches a generic object, creating a new prompt object in the process1276 * Enriches a generic object, creating a new prompt object in the process
1145 *1277 *
1146 * @param {Object} prompt - Prompt object1278 * @param {Partial<Prompt>} prompt - Prompt object
1147 * @param original1279 * @param original
1148 * @returns {Object} An object with "role" and "content" properties1280 * @returns {Prompt} An object with "role" and "content" properties
1149 */1281 */
1150 preparePrompt(prompt, original = null) {1282 preparePrompt(prompt, original = null) {
1151 const groupMembers = this.getActiveGroupCharacters();1283 const groupMembers = this.getActiveGroupCharacters();
@@ -1184,7 +1316,7 @@ class PromptManager {
11841316
1185 const debouncedSaveServiceSettings = debouncePromise(() => this.saveServiceSettings(), 300);1317 const debouncedSaveServiceSettings = debouncePromise(() => this.saveServiceSettings(), 300);
11861318
1187 const textarea = document.getElementById(textareaIdentifier);1319 const textarea = /** @type {HTMLTextAreaElement} */(document.getElementById(textareaIdentifier));
1188 textarea.addEventListener('blur', () => {1320 textarea.addEventListener('blur', () => {
1189 prompt.content = textarea.value;1321 prompt.content = textarea.value;
1190 this.updatePromptByIdentifier(identifier, prompt);1322 this.updatePromptByIdentifier(identifier, prompt);
@@ -1193,9 +1325,15 @@ class PromptManager {
11931325
1194 }1326 }
11951327
1328 /**
1329 * Updates the quick edit textarea for a specific prompt.
1330 * @param {string} identifier - The identifier of the prompt.
1331 * @param {Prompt} prompt - The updated prompt object.
1332 * @returns {string} The ID of the updated textarea element.
1333 */
1196 updateQuickEdit(identifier, prompt) {1334 updateQuickEdit(identifier, prompt) {
1197 const elementId = `${identifier}_prompt_quick_edit_textarea`;1335 const elementId = `${identifier}_prompt_quick_edit_textarea`;
1198 const textarea = document.getElementById(elementId);1336 const textarea = /** @type {HTMLTextAreaElement} */(document.getElementById(elementId));
1199 textarea.value = prompt.content;1337 textarea.value = prompt.content;
12001338
1201 return elementId;1339 return elementId;
@@ -1220,30 +1358,35 @@ class PromptManager {
12201358
1221 /**1359 /**
1222 * Loads a given prompt into the edit form fields.1360 * Loads a given prompt into the edit form fields.
1223 * @param {Object} prompt - Prompt object with properties 'name', 'role', 'content', and 'system_prompt'1361 * @param {Partial<Prompt>} prompt - Prompt object with properties 'name', 'role', 'content', and 'system_prompt'
1224 */1362 */
1225 loadPromptIntoEditForm(prompt) {1363 loadPromptIntoEditForm(prompt) {
1226 const nameField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name');1364 const nameField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name'));
1227 const roleField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role');1365 const roleField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role'));
1228 const promptField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt');1366 const promptField = /** @type {HTMLTextAreaElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt'));
1229 const injectionPositionField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position');1367 const injectionPositionField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position'));
1230 const injectionDepthField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth');1368 const injectionDepthField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth'));
1231 const injectionOrderField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_order');1369 const injectionOrderField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_order'));
1232 const injectionDepthBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_depth_block');1370 const injectionTriggerField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_trigger'));
1233 const injectionOrderBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_order_block');1371 const injectionDepthBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_depth_block'));
1234 const forbidOverridesField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides');1372 const injectionOrderBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_order_block'));
1235 const forbidOverridesBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_forbid_overrides_block');1373 const forbidOverridesField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides'));
1236 const entrySourceBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source_block');1374 const forbidOverridesBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_forbid_overrides_block'));
1237 const entrySource = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source');1375 const entrySourceBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source_block'));
1376 const entrySource = /** @type {HTMLSpanElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source'));
1238 const isPulledPrompt = Object.keys(this.promptSources).includes(prompt.identifier);1377 const isPulledPrompt = Object.keys(this.promptSources).includes(prompt.identifier);
12391378
1240 nameField.value = prompt.name ?? '';1379 nameField.value = prompt.name ?? '';
1241 roleField.value = prompt.role || 'system';1380 roleField.value = prompt.role || 'system';
1242 promptField.value = prompt.content ?? '';1381 promptField.value = prompt.content ?? '';
1243 promptField.disabled = prompt.marker ?? false;1382 promptField.disabled = prompt.marker ?? false;
1244 injectionPositionField.value = prompt.injection_position ?? INJECTION_POSITION.RELATIVE;1383 injectionPositionField.value = (prompt.injection_position ?? INJECTION_POSITION.RELATIVE).toString();
1245 injectionDepthField.value = prompt.injection_depth ?? DEFAULT_DEPTH;1384 injectionDepthField.value = (prompt.injection_depth ?? DEFAULT_DEPTH).toString();
1246 injectionOrderField.value = prompt.injection_order ?? 100;1385 injectionOrderField.value = (prompt.injection_order ?? DEFAULT_ORDER).toString();
1386 Array.from(injectionTriggerField.options).forEach(option => {
1387 option.selected = Array.isArray(prompt.injection_trigger) && prompt.injection_trigger.includes(option.value);
1388 });
1389 injectionTriggerField.dispatchEvent(new Event('change', { bubbles: true }));
1247 injectionDepthBlock.style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';1390 injectionDepthBlock.style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';
1248 injectionOrderBlock.style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';1391 injectionOrderBlock.style.visibility = prompt.injection_position === INJECTION_POSITION.ABSOLUTE ? 'visible' : 'hidden';
1249 injectionPositionField.removeAttribute('disabled');1392 injectionPositionField.removeAttribute('disabled');
@@ -1335,17 +1478,19 @@ class PromptManager {
1335 const editArea = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_edit');1478 const editArea = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_edit');
1336 editArea.style.display = 'none';1479 editArea.style.display = 'none';
13371480
1338 const nameField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name');1481 const nameField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_name'));
1339 const roleField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role');1482 const roleField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_role'));
1340 const promptField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt');1483 const promptField = /** @type {HTMLTextAreaElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_prompt'));
1341 const injectionPositionField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position');1484 const injectionPositionField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_position'));
1342 const injectionDepthField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth');1485 const injectionDepthField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_depth'));
1343 const injectionDepthBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_depth_block');1486 const injectionDepthBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_depth_block'));
1344 const injectionOrderBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_order_block');1487 const injectionOrderBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_order_block'));
1345 const forbidOverridesField = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides');1488 const injectionOrderField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_order'));
1346 const forbidOverridesBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_forbid_overrides_block');1489 const injectionTriggerField = /** @type {HTMLSelectElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_injection_trigger'));
1347 const entrySourceBlock = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source_block');1490 const forbidOverridesField = /** @type {HTMLInputElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_form_forbid_overrides'));
1348 const entrySource = document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source');1491 const forbidOverridesBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_forbid_overrides_block'));
1492 const entrySourceBlock = /** @type {HTMLDivElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source_block'));
1493 const entrySource = /** @type {HTMLSpanElement} */(document.getElementById(this.configuration.prefix + 'prompt_manager_popup_entry_source'));
13491494
1350 nameField.value = '';1495 nameField.value = '';
1351 roleField.selectedIndex = 0;1496 roleField.selectedIndex = 0;
@@ -1353,7 +1498,9 @@ class PromptManager {
1353 promptField.disabled = false;1498 promptField.disabled = false;
1354 injectionPositionField.selectedIndex = 0;1499 injectionPositionField.selectedIndex = 0;
1355 injectionPositionField.removeAttribute('disabled');1500 injectionPositionField.removeAttribute('disabled');
1356 injectionDepthField.value = DEFAULT_DEPTH;1501 injectionDepthField.value = DEFAULT_DEPTH.toString();
1502 injectionOrderField.value = DEFAULT_ORDER.toString();
1503 injectionTriggerField.value = '';
1357 injectionDepthBlock.style.visibility = 'unset';1504 injectionDepthBlock.style.visibility = 'unset';
1358 injectionOrderBlock.style.visibility = 'unset';1505 injectionOrderBlock.style.visibility = 'unset';
1359 forbidOverridesBlock.style.visibility = 'unset';1506 forbidOverridesBlock.style.visibility = 'unset';
@@ -1373,22 +1520,30 @@ class PromptManager {
13731520
1374 /**1521 /**
1375 * Returns a full list of prompts whose content markers have been substituted.1522 * Returns a full list of prompts whose content markers have been substituted.
1523 * @param {string} generationType - The type of generation, e.g., 'continue' or 'quiet'.
1376 * @returns {PromptCollection} A PromptCollection object1524 * @returns {PromptCollection} A PromptCollection object
1377 */1525 */
1378 getPromptCollection() {1526 getPromptCollection(generationType) {
1527 generationType = String(generationType || 'normal').toLowerCase().trim();
1528 const promptCollection = new PromptCollection();
1379 const promptOrder = this.getPromptOrderForCharacter(this.activeCharacter);1529 const promptOrder = this.getPromptOrderForCharacter(this.activeCharacter);
13801530
1381 const promptCollection = new PromptCollection();
1382 promptOrder.forEach(entry => {1531 promptOrder.forEach(entry => {
1383 if (true === entry.enabled) {
1384 const prompt = this.getPromptById(entry.identifier);1532 const prompt = this.getPromptById(entry.identifier);
1385 if (prompt) promptCollection.add(this.preparePrompt(prompt));1533 const allowedTrigger = entry.enabled && this.shouldTrigger(prompt, generationType);
1386 } else if (!entry.enabled && entry.identifier === 'main') {1534
1535 if (!prompt) {
1536 return;
1537 }
1538
1539 if (allowedTrigger) {
1540 promptCollection.add(this.preparePrompt(prompt));
1541 } else if (entry.identifier === 'main') {
1387 // Some extensions require main prompt to be present for relative inserts.1542 // Some extensions require main prompt to be present for relative inserts.
1388 // So we make a GMO-free vegan replacement.1543 // So we make a GMO-free vegan replacement.
1389 const prompt = structuredClone(this.getPromptById(entry.identifier));1544 const replacementPrompt = structuredClone(prompt);
1390 prompt.content = '';1545 replacementPrompt.content = '';
1391 if (prompt) promptCollection.add(this.preparePrompt(prompt));1546 promptCollection.add(this.preparePrompt(replacementPrompt));
1392 }1547 }
1393 });1548 });
13941549
@@ -1396,6 +1551,18 @@ class PromptManager {
1396 }1551 }
13971552
1398 /**1553 /**
1554 * Checks if a prompt should be triggered based on its injection triggers.
1555 * @param {Prompt} prompt - The prompt to check.
1556 * @param {string} generationType - The type of generation to check against.
1557 * @returns {boolean} True if the prompt should be triggered, false otherwise.
1558 */
1559 shouldTrigger(prompt, generationType) {
1560 if (!Array.isArray(prompt?.injection_trigger)) return true;
1561 if (!prompt.injection_trigger.length) return true;
1562 return prompt.injection_trigger.includes(generationType);
1563 }
1564
1565 /**
1399 * Setter for messages property1566 * Setter for messages property
1400 *1567 *
1401 * @param {import('./openai.js').MessageCollection} messages1568 * @param {import('./openai.js').MessageCollection} messages
@@ -1807,11 +1974,7 @@ class PromptManager {
1807 * @returns {string} A string representation of an uuid41974 * @returns {string} A string representation of an uuid4
1808 */1975 */
1809 getUuidv4() {1976 getUuidv4() {
1810 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {1977 return uuidv4();
1811 let r = Math.random() * 16 | 0,
1812 v = c === 'x' ? r : (r & 0x3 | 0x8);
1813 return v.toString(16);
1814 });
1815 }1978 }
18161979
1817 /**1980 /**
public/scripts/group-chats.js+1 -1
@@ -921,7 +921,6 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
921 for (const chId of activatedMembers) {921 for (const chId of activatedMembers) {
922 throwIfAborted();922 throwIfAborted();
923 deactivateSendButtons();923 deactivateSendButtons();
924 const generateType = type == 'swipe' || type == 'impersonate' || type == 'quiet' || type == 'continue' ? type : 'group_chat';
925 setCharacterId(chId);924 setCharacterId(chId);
926 setCharacterName(characters[chId].name);925 setCharacterName(characters[chId].name);
927 if (power_user.show_group_chat_queue) {926 if (power_user.show_group_chat_queue) {
@@ -930,6 +929,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
930 await eventSource.emit(event_types.GROUP_MEMBER_DRAFTED, chId);929 await eventSource.emit(event_types.GROUP_MEMBER_DRAFTED, chId);
931930
932 // Wait for generation to finish931 // Wait for generation to finish
932 const generateType = ['swipe', 'impersonate', 'quiet', 'continue'].includes(type) ? type : 'normal';
933 textResult = await Generate(generateType, { automatic_trigger: by_auto_mode, ...(params || {}) });933 textResult = await Generate(generateType, { automatic_trigger: by_auto_mode, ...(params || {}) });
934 let messageChunk = textResult?.messageChunk;934 let messageChunk = textResult?.messageChunk;
935935
public/scripts/openai.js+11 -8
@@ -1255,12 +1255,12 @@ async function populateChatCompletion(prompts, chatCompletion, { bias, quietProm
1255 * @param {string} options.quietPrompt - The quiet prompt to be used in the conversation.1255 * @param {string} options.quietPrompt - The quiet prompt to be used in the conversation.
1256 * @param {string} options.bias - The bias to be added in the conversation.1256 * @param {string} options.bias - The bias to be added in the conversation.
1257 * @param {Object} options.extensionPrompts - An object containing additional prompts.1257 * @param {Object} options.extensionPrompts - An object containing additional prompts.
1258 * @param {string} options.systemPromptOverride1258 * @param {string} options.systemPromptOverride - Character card override of the main prompt
1259 * @param {string} options.jailbreakPromptOverride1259 * @param {string} options.jailbreakPromptOverride - Character card override of the PHI
1260 * @param {string} options.personaDescription1260 * @param {string} options.type - The type of generation that triggered the prompt
1261 * @returns {Promise<Object>} prompts - The prepared and merged system and user-defined prompts.1261 * @returns {Promise<Object>} prompts - The prepared and merged system and user-defined prompts.
1262 */1262 */
1263async function preparePromptsForChatCompletion({ scenario, charPersonality, name2, worldInfoBefore, worldInfoAfter, charDescription, quietPrompt, bias, extensionPrompts, systemPromptOverride, jailbreakPromptOverride, personaDescription }) {1263async function preparePromptsForChatCompletion({ scenario, charPersonality, name2, worldInfoBefore, worldInfoAfter, charDescription, quietPrompt, bias, extensionPrompts, systemPromptOverride, jailbreakPromptOverride, type }) {
1264 const scenarioText = scenario && oai_settings.scenario_format ? substituteParams(oai_settings.scenario_format) : (scenario || '');1264 const scenarioText = scenario && oai_settings.scenario_format ? substituteParams(oai_settings.scenario_format) : (scenario || '');
1265 const charPersonalityText = charPersonality && oai_settings.personality_format ? substituteParams(oai_settings.personality_format) : (charPersonality || '');1265 const charPersonalityText = charPersonality && oai_settings.personality_format ? substituteParams(oai_settings.personality_format) : (charPersonality || '');
1266 const groupNudge = substituteParams(oai_settings.group_nudge_prompt);1266 const groupNudge = substituteParams(oai_settings.group_nudge_prompt);
@@ -1363,7 +1363,7 @@ async function preparePromptsForChatCompletion({ scenario, charPersonality, name
1363 }1363 }
13641364
1365 // This is the prompt order defined by the user1365 // This is the prompt order defined by the user
1366 const prompts = promptManager.getPromptCollection();1366 const prompts = promptManager.getPromptCollection(type);
13671367
1368 // Merge system prompts with prompt manager prompts1368 // Merge system prompts with prompt manager prompts
1369 systemPrompts.forEach(prompt => {1369 systemPrompts.forEach(prompt => {
@@ -1429,7 +1429,6 @@ async function preparePromptsForChatCompletion({ scenario, charPersonality, name
1429 * @param {string} content.cyclePrompt - The last prompt used for chat message continuation.1429 * @param {string} content.cyclePrompt - The last prompt used for chat message continuation.
1430 * @param {string} content.systemPromptOverride - The system prompt override.1430 * @param {string} content.systemPromptOverride - The system prompt override.
1431 * @param {string} content.jailbreakPromptOverride - The jailbreak prompt override.1431 * @param {string} content.jailbreakPromptOverride - The jailbreak prompt override.
1432 * @param {string} content.personaDescription - The persona description.
1433 * @param {object} content.extensionPrompts - An array of additional prompts.1432 * @param {object} content.extensionPrompts - An array of additional prompts.
1434 * @param {object[]} content.messages - An array of messages to be used as chat history.1433 * @param {object[]} content.messages - An array of messages to be used as chat history.
1435 * @param {string[]} content.messageExamples - An array of messages to be used as dialogue examples.1434 * @param {string[]} content.messageExamples - An array of messages to be used as dialogue examples.
@@ -1451,7 +1450,6 @@ export async function prepareOpenAIMessages({
1451 cyclePrompt,1450 cyclePrompt,
1452 systemPromptOverride,1451 systemPromptOverride,
1453 jailbreakPromptOverride,1452 jailbreakPromptOverride,
1454 personaDescription,
1455 messages,1453 messages,
1456 messageExamples,1454 messageExamples,
1457}, dryRun) {1455}, dryRun) {
@@ -1478,7 +1476,7 @@ export async function prepareOpenAIMessages({
1478 extensionPrompts,1476 extensionPrompts,
1479 systemPromptOverride,1477 systemPromptOverride,
1480 jailbreakPromptOverride,1478 jailbreakPromptOverride,
1481 personaDescription,1479 type,
1482 });1480 });
14831481
1484 // Fill the chat completion with as much context as the budget allows1482 // Fill the chat completion with as much context as the budget allows
@@ -6429,6 +6427,11 @@ export function initOpenAI() {
6429 width: '100%',6427 width: '100%',
6430 templateResult: getAimlapiModelTemplate,6428 templateResult: getAimlapiModelTemplate,
6431 });6429 });
6430 $('#completion_prompt_manager_popup_entry_form_injection_trigger').select2({
6431 placeholder: t`All types (default)`,
6432 width: '100%',
6433 closeOnSelect: false,
6434 });
6432 }6435 }
64336436
6434 $('#openrouter_providers_chat').on('change', function () {6437 $('#openrouter_providers_chat').on('change', function () {
public/scripts/slash-commands.js+1 -1
@@ -3947,7 +3947,7 @@ async function askCharacter(args, text) {
3947 try {3947 try {
3948 eventSource.once(event_types.MESSAGE_RECEIVED, restoreCharacter);3948 eventSource.once(event_types.MESSAGE_RECEIVED, restoreCharacter);
3949 toastr.info(`Asking ${name} something...`);3949 toastr.info(`Asking ${name} something...`);
3950 askResult = await Generate('ask_command');3950 askResult = await Generate('normal');
3951 } catch (error) {3951 } catch (error) {
3952 restoreCharacter();3952 restoreCharacter();
3953 console.error('Error running /ask command', error);3953 console.error('Error running /ask command', error);