mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
add option to prevent recursive auto-execute
This commit is contained in:
@ -42,6 +42,10 @@
|
|||||||
|
|
||||||
<h3>Auto-Execute</h3>
|
<h3>Auto-Execute</h3>
|
||||||
<div class="flex-container flexFlowColumn">
|
<div class="flex-container flexFlowColumn">
|
||||||
|
<label class="checkbox_label" title="Prevent this quick reply from triggering other auto-executed quick replies while auto-executing (i.e., prevent recursive auto-execution)">
|
||||||
|
<input type="checkbox" id="qr--preventAutoExecute" >
|
||||||
|
<span><i class="fa-solid fa-fw fa-plane-slash"></i> Don't trigger auto-execute</span>
|
||||||
|
</label>
|
||||||
<label class="checkbox_label">
|
<label class="checkbox_label">
|
||||||
<input type="checkbox" id="qr--isHidden" >
|
<input type="checkbox" id="qr--isHidden" >
|
||||||
<span><i class="fa-solid fa-fw fa-eye-slash"></i> Invisible (auto-execute only)</span>
|
<span><i class="fa-solid fa-fw fa-eye-slash"></i> Invisible (auto-execute only)</span>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { chat_metadata, eventSource, event_types, getRequestHeaders } from '../../../script.js';
|
import { chat_metadata, eventSource, event_types, getRequestHeaders } from '../../../script.js';
|
||||||
import { extension_settings } from '../../extensions.js';
|
import { extension_settings } from '../../extensions.js';
|
||||||
import { QuickReplyApi } from './api/QuickReplyApi.js';
|
import { QuickReplyApi } from './api/QuickReplyApi.js';
|
||||||
|
import { AutoExecuteHandler } from './src/AutoExecuteHandler.js';
|
||||||
import { QuickReply } from './src/QuickReply.js';
|
import { QuickReply } from './src/QuickReply.js';
|
||||||
import { QuickReplyConfig } from './src/QuickReplyConfig.js';
|
import { QuickReplyConfig } from './src/QuickReplyConfig.js';
|
||||||
import { QuickReplyContextLink } from './src/QuickReplyContextLink.js';
|
import { QuickReplyContextLink } from './src/QuickReplyContextLink.js';
|
||||||
@ -64,6 +65,8 @@ let settings;
|
|||||||
let manager;
|
let manager;
|
||||||
/** @type {ButtonUi} */
|
/** @type {ButtonUi} */
|
||||||
let buttons;
|
let buttons;
|
||||||
|
/** @type {AutoExecuteHandler} */
|
||||||
|
let autoExec;
|
||||||
/** @type {QuickReplyApi} */
|
/** @type {QuickReplyApi} */
|
||||||
export let quickReplyApi;
|
export let quickReplyApi;
|
||||||
|
|
||||||
@ -174,20 +177,9 @@ const init = async () => {
|
|||||||
quickReplyApi = new QuickReplyApi(settings, manager);
|
quickReplyApi = new QuickReplyApi(settings, manager);
|
||||||
const slash = new SlashCommandHandler(quickReplyApi);
|
const slash = new SlashCommandHandler(quickReplyApi);
|
||||||
slash.init();
|
slash.init();
|
||||||
|
autoExec = new AutoExecuteHandler(settings);
|
||||||
|
|
||||||
if (settings.isEnabled) {
|
autoExec.handleStartup();
|
||||||
const qrList = [
|
|
||||||
...settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnStartup)).flat(),
|
|
||||||
...(settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnStartup))?.flat() ?? []),
|
|
||||||
];
|
|
||||||
for (const qr of qrList) {
|
|
||||||
try {
|
|
||||||
await qr.onExecute();
|
|
||||||
} catch (ex) {
|
|
||||||
warn(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
eventSource.on(event_types.APP_READY, init);
|
eventSource.on(event_types.APP_READY, init);
|
||||||
|
|
||||||
@ -201,52 +193,16 @@ const onChatChanged = async (chatIdx) => {
|
|||||||
manager.rerender();
|
manager.rerender();
|
||||||
buttons.refresh();
|
buttons.refresh();
|
||||||
|
|
||||||
if (settings.isEnabled) {
|
autoExec.handleChatChanged;
|
||||||
const qrList = [
|
|
||||||
...settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnChatChange)).flat(),
|
|
||||||
...(settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnChatChange))?.flat() ?? []),
|
|
||||||
];
|
|
||||||
for (const qr of qrList) {
|
|
||||||
try {
|
|
||||||
await qr.onExecute();
|
|
||||||
} catch (ex) {
|
|
||||||
warn(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
|
eventSource.on(event_types.CHAT_CHANGED, onChatChanged);
|
||||||
|
|
||||||
const onUserMessage = async () => {
|
const onUserMessage = async () => {
|
||||||
if (settings.isEnabled) {
|
autoExec.handleUser();
|
||||||
const qrList = [
|
|
||||||
...settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnUser)).flat(),
|
|
||||||
...(settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnUser))?.flat() ?? []),
|
|
||||||
];
|
|
||||||
for (const qr of qrList) {
|
|
||||||
try {
|
|
||||||
await qr.onExecute();
|
|
||||||
} catch (ex) {
|
|
||||||
warn(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
eventSource.on(event_types.USER_MESSAGE_RENDERED, onUserMessage);
|
eventSource.on(event_types.USER_MESSAGE_RENDERED, onUserMessage);
|
||||||
|
|
||||||
const onAiMessage = async () => {
|
const onAiMessage = async () => {
|
||||||
if (settings.isEnabled) {
|
autoExec.handleAi();
|
||||||
const qrList = [
|
|
||||||
...settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnAi)).flat(),
|
|
||||||
...(settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnAi))?.flat() ?? []),
|
|
||||||
];
|
|
||||||
for (const qr of qrList) {
|
|
||||||
try {
|
|
||||||
await qr.onExecute();
|
|
||||||
} catch (ex) {
|
|
||||||
warn(ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, onAiMessage);
|
eventSource.on(event_types.CHARACTER_MESSAGE_RENDERED, onAiMessage);
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
import { warn } from '../index.js';
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
import { QuickReply } from './QuickReply.js';
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
import { QuickReplySettings } from './QuickReplySettings.js';
|
||||||
|
|
||||||
|
export class AutoExecuteHandler {
|
||||||
|
/**@type {QuickReplySettings}*/ settings;
|
||||||
|
|
||||||
|
/**@type {Boolean[]}*/ preventAutoExecuteStack = [];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
constructor(/**@type {QuickReplySettings}*/settings) {
|
||||||
|
this.settings = settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
checkExecute() {
|
||||||
|
return this.settings.isEnabled && !this.preventAutoExecuteStack.slice(-1)[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
async performAutoExecute(/**@type {QuickReply[]}*/qrList) {
|
||||||
|
for (const qr of qrList) {
|
||||||
|
this.preventAutoExecuteStack.push(qr.preventAutoExecute);
|
||||||
|
try {
|
||||||
|
await qr.onExecute();
|
||||||
|
} catch (ex) {
|
||||||
|
warn(ex);
|
||||||
|
} finally {
|
||||||
|
this.preventAutoExecuteStack.pop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async handleStartup() {
|
||||||
|
if (!this.checkExecute()) return;
|
||||||
|
const qrList = [
|
||||||
|
...this.settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnStartup)).flat(),
|
||||||
|
...(this.settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnStartup))?.flat() ?? []),
|
||||||
|
];
|
||||||
|
await this.performAutoExecute(qrList);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleUser() {
|
||||||
|
if (!this.checkExecute()) return;
|
||||||
|
const qrList = [
|
||||||
|
...this.settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnUser)).flat(),
|
||||||
|
...(this.settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnUser))?.flat() ?? []),
|
||||||
|
];
|
||||||
|
await this.performAutoExecute(qrList);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleAi() {
|
||||||
|
if (!this.checkExecute()) return;
|
||||||
|
const qrList = [
|
||||||
|
...this.settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnAi)).flat(),
|
||||||
|
...(this.settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnAi))?.flat() ?? []),
|
||||||
|
];
|
||||||
|
await this.performAutoExecute(qrList);
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleChatChanged() {
|
||||||
|
if (!this.checkExecute()) return;
|
||||||
|
const qrList = [
|
||||||
|
...this.settings.config.setList.map(link=>link.set.qrList.filter(qr=>qr.executeOnChatChange)).flat(),
|
||||||
|
...(this.settings.chatConfig?.setList?.map(link=>link.set.qrList.filter(qr=>qr.executeOnChatChange))?.flat() ?? []),
|
||||||
|
];
|
||||||
|
await this.performAutoExecute(qrList);
|
||||||
|
}
|
||||||
|
}
|
@ -24,6 +24,7 @@ export class QuickReply {
|
|||||||
|
|
||||||
/**@type {QuickReplyContextLink[]}*/ contextList;
|
/**@type {QuickReplyContextLink[]}*/ contextList;
|
||||||
|
|
||||||
|
/**@type {Boolean}*/ preventAutoExecute = true;
|
||||||
/**@type {Boolean}*/ isHidden = false;
|
/**@type {Boolean}*/ isHidden = false;
|
||||||
/**@type {Boolean}*/ executeOnStartup = false;
|
/**@type {Boolean}*/ executeOnStartup = false;
|
||||||
/**@type {Boolean}*/ executeOnUser = false;
|
/**@type {Boolean}*/ executeOnUser = false;
|
||||||
@ -311,6 +312,13 @@ export class QuickReply {
|
|||||||
|
|
||||||
// auto-exec
|
// auto-exec
|
||||||
/**@type {HTMLInputElement}*/
|
/**@type {HTMLInputElement}*/
|
||||||
|
const preventAutoExecute = dom.querySelector('#qr--preventAutoExecute');
|
||||||
|
preventAutoExecute.checked = this.preventAutoExecute;
|
||||||
|
preventAutoExecute.addEventListener('click', ()=>{
|
||||||
|
this.preventAutoExecute = preventAutoExecute.checked;
|
||||||
|
this.updateContext();
|
||||||
|
});
|
||||||
|
/**@type {HTMLInputElement}*/
|
||||||
const isHidden = dom.querySelector('#qr--isHidden');
|
const isHidden = dom.querySelector('#qr--isHidden');
|
||||||
isHidden.checked = this.isHidden;
|
isHidden.checked = this.isHidden;
|
||||||
isHidden.addEventListener('click', ()=>{
|
isHidden.addEventListener('click', ()=>{
|
||||||
@ -462,6 +470,7 @@ export class QuickReply {
|
|||||||
title: this.title,
|
title: this.title,
|
||||||
message: this.message,
|
message: this.message,
|
||||||
contextList: this.contextList,
|
contextList: this.contextList,
|
||||||
|
preventAutoExecute: this.preventAutoExecute,
|
||||||
isHidden: this.isHidden,
|
isHidden: this.isHidden,
|
||||||
executeOnStartup: this.executeOnStartup,
|
executeOnStartup: this.executeOnStartup,
|
||||||
executeOnUser: this.executeOnUser,
|
executeOnUser: this.executeOnUser,
|
||||||
|
Reference in New Issue
Block a user