Merge pull request #2806 from SillyTavern/bypass-command-string-parser Execute profile commands callbacks directly

b2705d13964f79a96b8dea950d5d1af4c7909333

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

Signed
1 files changed, +29 -11Ignore whitespace
public/scripts/extensions/connection-manager/index.js+29 -11
@@ -1,12 +1,14 @@
1import { event_types, eventSource, main_api, saveSettingsDebounced } from '../../../script.js';1import { event_types, eventSource, main_api, saveSettingsDebounced } from '../../../script.js';
2import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js';2import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js';
3import { callGenericPopup, Popup, POPUP_TYPE } from '../../popup.js';3import { callGenericPopup, Popup, POPUP_TYPE } from '../../popup.js';
4import { executeSlashCommandsWithOptions } from '../../slash-commands.js';
5import { SlashCommand } from '../../slash-commands/SlashCommand.js';4import { SlashCommand } from '../../slash-commands/SlashCommand.js';
5import { SlashCommandAbortController } from '../../slash-commands/SlashCommandAbortController.js';
6import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';6import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
7import { commonEnumProviders, enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';7import { commonEnumProviders, enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js';
8import { SlashCommandDebugController } from '../../slash-commands/SlashCommandDebugController.js';
8import { enumTypes, SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js';9import { enumTypes, SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js';
9import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';10import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
11import { SlashCommandScope } from '../../slash-commands/SlashCommandScope.js';
10import { collapseSpaces, getUniqueName, isFalseBoolean, uuidv4 } from '../../utils.js';12import { collapseSpaces, getUniqueName, isFalseBoolean, uuidv4 } from '../../utils.js';
1113
12const MODULE_NAME = 'connection-manager';14const MODULE_NAME = 'connection-manager';
@@ -91,6 +93,24 @@ class ConnectionManagerSpinner {
91 }93 }
92}94}
9395
96/**
97 * Get named arguments for the command callback.
98 * @param {object} [args] Additional named arguments
99 * @returns {object} Named arguments
100 */
101function getNamedArguments(args = {}) {
102 // None of the commands here use underscored args, but better safe than sorry
103 return {
104 _scope: new SlashCommandScope(),
105 _abortController: new SlashCommandAbortController(),
106 _debugController: new SlashCommandDebugController(),
107 _parserFlags: {},
108 _hasUnnamedArgument: false,
109 quiet: 'true',
110 ...args,
111 };
112}
113
94/** @type {() => SlashCommandEnumValue[]} */114/** @type {() => SlashCommandEnumValue[]} */
95const profilesProvider = () => [115const profilesProvider = () => [
96 new SlashCommandEnumValue(NONE),116 new SlashCommandEnumValue(NONE),
@@ -112,8 +132,6 @@ const profilesProvider = () => [
112 * @property {string} [tokenizer] Tokenizer132 * @property {string} [tokenizer] Tokenizer
113 */133 */
114134
115const escapeArgument = (a) => a.replace(/"/g, '\\"').replace(/\|/g, '\\|');
116
117/**135/**
118 * Finds the best match for the search value.136 * Finds the best match for the search value.
119 * @param {string} value Search value137 * @param {string} value Search value
@@ -149,15 +167,15 @@ async function readProfileFromCommands(mode, profile, cleanUp = false) {
149 const commands = mode === 'cc' ? CC_COMMANDS : TC_COMMANDS;167 const commands = mode === 'cc' ? CC_COMMANDS : TC_COMMANDS;
150 const opposingCommands = mode === 'cc' ? TC_COMMANDS : CC_COMMANDS;168 const opposingCommands = mode === 'cc' ? TC_COMMANDS : CC_COMMANDS;
151 for (const command of commands) {169 for (const command of commands) {
152 const commandText = `/${command} quiet=true`;
153 try {170 try {
154 const result = await executeSlashCommandsWithOptions(commandText, { handleParserErrors: false, handleExecutionErrors: false });171 const args = getNamedArguments();
155 if (result.pipe) {172 const result = await SlashCommandParser.commands[command].callback(args, '');
156 profile[command] = result.pipe;173 if (result) {
174 profile[command] = result;
157 continue;175 continue;
158 }176 }
159 } catch (error) {177 } catch (error) {
160 console.warn(`Failed to execute command: ${commandText}`, error);178 console.error(`Failed to execute command: ${command}`, error);
161 }179 }
162 }180 }
163181
@@ -273,11 +291,11 @@ async function applyConnectionProfile(profile) {
273 if (!argument) {291 if (!argument) {
274 continue;292 continue;
275 }293 }
276 const commandText = `/${command} quiet=true ${escapeArgument(argument)}`;
277 try {294 try {
278 await executeSlashCommandsWithOptions(commandText, { handleParserErrors: false, handleExecutionErrors: false });295 const args = getNamedArguments();
296 await SlashCommandParser.commands[command].callback(args, argument);
279 } catch (error) {297 } catch (error) {
280 console.error(`Failed to execute command: ${commandText}`, error);298 console.error(`Failed to execute command: ${command} ${argument}`, error);
281 }299 }
282 }300 }
283301