Merge pull request #2465 from SillyTavern/stop-gen-slash-command /stop slash command to stop generation

7820ec66b92cea4c72e017ba705bdb12a30766da

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

Signed
2 files changed, +48 -11Showing whitespace changes
public/script.js+29 -11
@@ -227,7 +227,7 @@ import { appendFileContent, hasPendingFileAttachment, populateFileAttachment, de
227227import { initPresetManager } from './scripts/preset-manager.js';
228228import { MacrosParser, evaluateMacros } from './scripts/macros.js';
229229import { currentUser, setUserControls } from './scripts/user.js';
230230import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup, fixToastrForDialogs } from './scripts/popup.js';
231231import { renderTemplate, renderTemplateAsync } from './scripts/templates.js';
232232import { ScraperManager } from './scripts/scrapers.js';
233233import { SlashCommandParser } from './scripts/slash-commands/SlashCommandParser.js';
@@ -520,6 +520,7 @@ const chatElement = $('#chat');
520520let dialogueResolve = null;
521521let dialogueCloseStop = false;
522522export let chat_metadata = {};
523+/** @type {StreamingProcessor} */
523524export let streamingProcessor = null;
524525let crop_data = undefined;
525526let is_delete_mode = false;
@@ -837,6 +838,7 @@ export let main_api;// = "kobold";
837838//novel settings
838839export let novelai_settings;
839840export let novelai_setting_names;
841+/** @type {AbortController} */
840842let abortController;
841843
842844//css
@@ -4381,6 +4383,25 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
43814383}
43824384
43834385/**
4386+ * Stops the generation and any streaming if it is currently running.
4387+ */
4388+export function stopGeneration() {
4389+ let stopped = false;
4390+ if (streamingProcessor) {
4391+ streamingProcessor.onStopStreaming();
4392+ streamingProcessor = null;
4393+ stopped = true;
4394+ }
4395+ if (abortController) {
4396+ abortController.abort('Clicked stop button');
4397+ hideStopButton();
4398+ stopped = true;
4399+ }
4400+ eventSource.emit(event_types.GENERATION_STOPPED);
4401+ return stopped;
4402+}
4403+
4404+/**
43844405 * Injects extension prompts into chat messages.
43854406 * @param {object[]} messages Array of chat messages
43864407 * @param {boolean} isContinue Whether the generation is a continuation. If true, the extension prompts of depth 0 are injected at position 1.
@@ -7163,7 +7184,8 @@ function onScenarioOverrideRemoveClick() {
71637184 * @param {string} inputValue - Value to set the input to.
71647185 * @param {PopupOptions} options - Options for the popup.
71657186 * @typedef {{okButton?: string, rows?: number, wide?: boolean, wider?: boolean, large?: boolean, allowHorizontalScrolling?: boolean, allowVerticalScrolling?: boolean, cropAspect?: number }} PopupOptions - Options for the popup.
7166- * @returns
7187+ * @returns {Promise<any>} A promise that resolves when the popup is closed.
7188+ * @deprecated Use `callGenericPopup` instead.
71677189 */
71687190export function callPopup(text, type, inputValue = '', { okButton, rows, wide, wider, large, allowHorizontalScrolling, allowVerticalScrolling, cropAspect } = {}) {
71697191 function getOkButtonText() {
@@ -7794,6 +7816,7 @@ window['SillyTavern'].getContext = function () {
77947816 eventTypes: event_types,
77957817 addOneMessage: addOneMessage,
77967818 generate: Generate,
7819+ stopGeneration: stopGeneration,
77977820 getTokenCount: getTokenCount,
77987821 extensionPrompts: extension_prompts,
77997822 setExtensionPrompt: setExtensionPrompt,
@@ -7849,6 +7872,8 @@ window['SillyTavern'].getContext = function () {
78497872 * @deprecated Legacy snake-case naming, compatibility with old extensions
78507873 */
78517874 event_types: event_types,
7875+ POPUP_TYPE: POPUP_TYPE,
7876+ POPUP_RESULT: POPUP_RESULT,
78527877 };
78537878};
78547879
@@ -10342,15 +10367,7 @@ jQuery(async function () {
1034210367 });
1034310368
1034410369 $(document).on('click', '.mes_stop', function () {
10345- if (streamingProcessor) {
10370+ stopGeneration();
10346- streamingProcessor.onStopStreaming();
10347- streamingProcessor = null;
10348- }
10349- if (abortController) {
10350- abortController.abort('Clicked stop button');
10351- hideStopButton();
10352- }
10353- eventSource.emit(event_types.GENERATION_STOPPED);
1035410371 });
1035510372
1035610373 $(document).on('click', '#form_sheld .stscript_continue', function () {
@@ -10839,3 +10856,4 @@ jQuery(async function () {
1083910856
1084010857 initCustomSelectedSamplers();
1084110858});
10859+
public/scripts/slash-commands.js+19 -0
@@ -33,6 +33,7 @@ import {
3333 setCharacterName,
3434 setExtensionPrompt,
3535 setUserName,
36+ stopGeneration,
3637 substituteParams,
3738 system_avatar,
3839 system_message_types,
@@ -899,6 +900,24 @@ export function initDefaultSlashCommands() {
899900 helpString: 'Adds a swipe to the last chat message.',
900901 }));
901902 SlashCommandParser.addCommandObject(SlashCommand.fromProps({
903+ name: 'stop',
904+ callback: () => {
905+ const stopped = stopGeneration();
906+ return String(stopped);
907+ },
908+ returns: 'true/false, whether the generation was running and got stopped',
909+ helpString: `
910+ <div>
911+ Stops the generation and any streaming if it is currently running.
912+ </div>
913+ <div>
914+ Note: This command cannot be executed from the chat input, as sending any message or script from there is blocked during generation.
915+ But it can be executed via automations or QR scripts/buttons.
916+ </div>
917+ `,
918+ aliases: ['generate-stop'],
919+ }));
920+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
902921 name: 'abort',
903922 callback: abortCallback,
904923 namedArgumentList: [