Merge pull request #3368 from SillyTavern/profile-stopstrings Add command and profile for custom stop strings

26feb448a3efe0673fbe1f82e490dd6efe93f781

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

Signed
2 files changed, +45 -0Ignore whitespace
public/scripts/extensions/connection-manager/index.js+4 -0
@@ -30,6 +30,7 @@ const CC_COMMANDS = [
3030 'api-url',
3131 'model',
3232 'proxy',
33+ 'stop-strings',
3334];
3435
3536const TC_COMMANDS = [
@@ -43,6 +44,7 @@ const TC_COMMANDS = [
4344 'context',
4445 'instruct-state',
4546 'tokenizer',
47+ 'stop-strings',
4648];
4749
4850const FANCY_NAMES = {
@@ -57,6 +59,7 @@ const FANCY_NAMES = {
5759 'instruct': 'Instruct Template',
5860 'context': 'Context Template',
5961 'tokenizer': 'Tokenizer',
62+ 'stop-strings': 'Custom Stopping Strings',
6063};
6164
6265/**
@@ -138,6 +141,7 @@ const profilesProvider = () => [
138141 * @property {string} [context] Context Template
139142 * @property {string} [instruct-state] Instruct Mode
140143 * @property {string} [tokenizer] Tokenizer
144+ * @property {string} [stop-strings] Custom Stopping Strings
141145 * @property {string[]} [exclude] Commands to exclude
142146 */
143147
public/scripts/power-user.js+41 -0
@@ -4072,4 +4072,45 @@ $(document).ready(() => {
40724072 ],
40734073 helpString: 'activates a movingUI preset by name',
40744074 }));
4075+ SlashCommandParser.addCommandObject(SlashCommand.fromProps({
4076+ name: 'stop-strings',
4077+ aliases: ['stopping-strings', 'custom-stopping-strings', 'custom-stop-strings'],
4078+ helpString: `
4079+ <div>
4080+ Sets a list of custom stopping strings. Gets the list if no value is provided.
4081+ </div>
4082+ <div>
4083+ <strong>Examples:</strong>
4084+ </div>
4085+ <ul>
4086+ <li>Value must be a JSON-serialized array: <pre><code class="language-stscript">/stop-strings ["goodbye", "farewell"]</code></pre></li>
4087+ <li>Pipe characters must be escaped with a backslash: <pre><code class="language-stscript">/stop-strings ["left\\|right"]</code></pre></li>
4088+ </ul>
4089+ `,
4090+ returns: ARGUMENT_TYPE.LIST,
4091+ unnamedArgumentList: [
4092+ SlashCommandArgument.fromProps({
4093+ description: 'list of strings',
4094+ typeList: [ARGUMENT_TYPE.LIST],
4095+ acceptsMultiple: false,
4096+ isRequired: false,
4097+ }),
4098+ ],
4099+ callback: (_, value) => {
4100+ if (String(value ?? '').trim()) {
4101+ const parsedValue = ((x) => { try { return JSON.parse(x.toString()); } catch { return null; } })(value);
4102+ if (!parsedValue || !Array.isArray(parsedValue)) {
4103+ throw new Error('Invalid list format. The value must be a JSON-serialized array of strings.');
4104+ }
4105+ parsedValue.forEach((item, index) => {
4106+ parsedValue[index] = String(item);
4107+ });
4108+ power_user.custom_stopping_strings = JSON.stringify(parsedValue);
4109+ $('#custom_stopping_strings').val(power_user.custom_stopping_strings);
4110+ saveSettingsDebounced();
4111+ }
4112+
4113+ return power_user.custom_stopping_strings;
4114+ },
4115+ }));
40754116});