mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
use /run to call closures and no arguments on immediate closures
This commit is contained in:
@ -52,6 +52,8 @@ import { textgen_types, textgenerationwebui_settings } from './textgen-settings.
|
||||
import { decodeTextTokens, getFriendlyTokenizerName, getTextTokens, getTokenCount } from './tokenizers.js';
|
||||
import { debounce, delay, escapeRegex, isFalseBoolean, isTrueBoolean, stringToRange, trimToEndSentence, trimToStartSentence, waitUntilCondition } from './utils.js';
|
||||
import { registerVariableCommands, resolveVariable } from './variables.js';
|
||||
import { SlashCommandScope } from './slash-commands/SlashCommandScope.js';
|
||||
import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
|
||||
export {
|
||||
executeSlashCommands, getSlashCommandsHelp, registerSlashCommand,
|
||||
};
|
||||
@ -523,21 +525,35 @@ function getMessagesCallback(args, value) {
|
||||
|
||||
async function runCallback(args, name) {
|
||||
if (!name) {
|
||||
toastr.warning('No name provided for /run command');
|
||||
return '';
|
||||
throw new Error('No name provided for /run command');
|
||||
}
|
||||
|
||||
/**@type {SlashCommandScope} */
|
||||
const scope = args._scope;
|
||||
if (scope.existsVariable(name)) {
|
||||
const closure = scope.getVariable(name);
|
||||
if (!(closure instanceof SlashCommandClosure)) {
|
||||
throw new Error(`"${name}" is not callable.`);
|
||||
}
|
||||
closure.scope.parent = scope;
|
||||
Object.keys(closure.arguments).forEach(key=>{
|
||||
if (Object.keys(args).includes(key)) {
|
||||
closure.providedArguments[key] = args[key];
|
||||
}
|
||||
});
|
||||
const result = await closure.execute();
|
||||
return result.pipe;
|
||||
}
|
||||
|
||||
if (typeof window['executeQuickReplyByName'] !== 'function') {
|
||||
toastr.warning('Quick Reply extension is not loaded');
|
||||
return '';
|
||||
throw new Error('Quick Reply extension is not loaded');
|
||||
}
|
||||
|
||||
try {
|
||||
name = name.trim();
|
||||
return await window['executeQuickReplyByName'](name, args);
|
||||
} catch (error) {
|
||||
toastr.error(`Error running Quick Reply "${name}": ${error.message}`, 'Error');
|
||||
return '';
|
||||
throw new Error(`Error running Quick Reply "${name}": ${error.message}`, 'Error');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,7 +11,7 @@ export class SlashCommandClosure {
|
||||
/**@type {Map<string,string|SlashCommandClosure>}*/ arguments = {};
|
||||
// @ts-ignore
|
||||
/**@type {Map<string,string|SlashCommandClosure>}*/ providedArguments = {};
|
||||
/**@type {(SlashCommandExecutor|SlashCommandClosureExecutor)[]}*/ executorList = [];
|
||||
/**@type {SlashCommandExecutor[]}*/ executorList = [];
|
||||
/**@type {String}*/ keptText;
|
||||
|
||||
constructor(parent) {
|
||||
|
@ -233,9 +233,6 @@ export class SlashCommandParser {
|
||||
this.discardWhitespace();
|
||||
}
|
||||
while (!this.testClosureEnd()) {
|
||||
if (this.testClosureCall()) {
|
||||
closure.executorList.push(this.parseClosureCall());
|
||||
}
|
||||
if (this.testCommand()) {
|
||||
closure.executorList.push(this.parseCommand());
|
||||
} else {
|
||||
@ -244,57 +241,15 @@ export class SlashCommandParser {
|
||||
while (/\s|\|/.test(this.char)) this.take(); // discard whitespace and pipe (command separator)
|
||||
}
|
||||
this.take(2); // discard closing :}
|
||||
this.discardWhitespace();
|
||||
if (this.char == '(') {
|
||||
this.take(); // discard opening (
|
||||
if (this.char == '(' && this.ahead[0] == ')') {
|
||||
this.take(2); // discard ()
|
||||
closure.executeNow = true;
|
||||
this.discardWhitespace();
|
||||
while (this.testNamedArgument()) {
|
||||
const arg = this.parseNamedArgument();
|
||||
if (!Object.keys(closure.arguments).includes(arg.key)) throw new SlashCommandParserError(`Invalid named argument for closure "${arg.key}" at position ${this.index - 2}`, this.text, this.index);
|
||||
closure.providedArguments[arg.key] = arg.value;
|
||||
this.discardWhitespace();
|
||||
}
|
||||
// @ts-ignore
|
||||
if (this.char != ')') throw new SlashCommandParserError(`Missing closing ")" at position ${this.index - 2}.`, this.text, this.index);
|
||||
this.take(); // discard closing )
|
||||
}
|
||||
while (/\s/.test(this.char)) this.take(); // discard trailing whitespace
|
||||
this.discardWhitespace(); // discard trailing whitespace
|
||||
this.scope = closure.scope.parent;
|
||||
return closure;
|
||||
}
|
||||
|
||||
testClosureCall() {
|
||||
return this.char == '/'
|
||||
&& this.behind.slice(-1) != '\\'
|
||||
&& !['/', '#'].includes(this.ahead[0])
|
||||
&& /^\S+\(/.test(this.ahead)
|
||||
;
|
||||
}
|
||||
testClosureCallEnd() {
|
||||
return this.char == ')' && this.behind.slice(-1) != '\\';
|
||||
}
|
||||
parseClosureCall() {
|
||||
this.take(); // discard /
|
||||
let name = '';
|
||||
while (!/\s|\(/.test(this.char)) name += this.take(); // take chars until opening (
|
||||
this.take(); // discard opening (
|
||||
const executor = new SlashCommandClosureExecutor();
|
||||
executor.name = name;
|
||||
this.discardWhitespace();
|
||||
while (this.testNamedArgument()) {
|
||||
const arg = this.parseNamedArgument();
|
||||
executor.providedArguments[arg.key] = arg.value;
|
||||
this.discardWhitespace();
|
||||
}
|
||||
if (this.testClosureCallEnd()) {
|
||||
this.take(); // discard closing )
|
||||
return executor;
|
||||
} else {
|
||||
throw new SlashCommandParserError(`Unexpected end of closure call at position ${this.index - 2}`, this.text, this.index);
|
||||
}
|
||||
}
|
||||
|
||||
testCommand() {
|
||||
return this.char == '/' && this.behind.slice(-1) != '\\' && !['/', '#'].includes(this.ahead[0]);
|
||||
}
|
||||
|
Reference in New Issue
Block a user