Add slash commands and connection profiles support
| @@ -33,6 +33,8 @@ const CC_COMMANDS = [ | ||
| 33 | 33 | |
| 34 | 34 | const TC_COMMANDS = [ |
| 35 | 35 | ...COMMON_COMMANDS, |
| 36 | + 'sysprompt', | |
| 37 | + 'sysprompt-state', | |
| 36 | 38 | 'instruct', |
| 37 | 39 | 'context', |
| 38 | 40 | 'instruct-state', |
| @@ -45,6 +47,8 @@ const FANCY_NAMES = { | ||
| 45 | 47 | 'preset': 'Settings Preset', |
| 46 | 48 | 'model': 'Model', |
| 47 | 49 | 'proxy': 'Proxy Preset', |
| 50 | + 'sysprompt-state': 'Use System Prompt', | |
| 51 | + 'sysprompt': 'System Prompt Name', | |
| 48 | 52 | 'instruct-state': 'Instruct Mode', |
| 49 | 53 | 'instruct': 'Instruct Template', |
| 50 | 54 | 'context': 'Context Template', |
| @@ -180,6 +184,11 @@ async function readProfileFromCommands(mode, profile, cleanUp = false) { | ||
| 180 | 184 | } |
| 181 | 185 | |
| 182 | 186 | if (cleanUp) { |
| 187 | + for (const command of commands) { | |
| 188 | + if (command.endsWith('-state') && profile[command] === 'false') { | |
| 189 | + delete profile[command.replace('-state', '')]; | |
| 190 | + } | |
| 191 | + } | |
| 183 | 192 | for (const command of opposingCommands) { |
| 184 | 193 | if (commands.includes(command)) { |
| 185 | 194 | continue; |
| @@ -1,6 +1,11 @@ | ||
| 1 | 1 | import { saveSettingsDebounced } from '../script.js'; |
| 2 | 2 | import { power_user } from './power-user.js'; |
| 3 | 3 | import { resetScrollHeightSlashCommand } from './utilsslash-commands/SlashCommand.js'; |
| 4 | +import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js'; | |
| 5 | +import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js'; | |
| 6 | +import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js'; | |
| 7 | +import { SlashCommandParser } from './slash-commands/SlashCommandParser.js'; | |
| 8 | +import { isTrueBoolean, resetScrollHeight } from './utils.js'; | |
| 4 | 9 | |
| 5 | 10 | export let system_prompts = []; |
| 6 | 11 | |
| @@ -53,6 +58,57 @@ function toggleSyspromptDisabledControls() { | ||
| 53 | 58 | $contentBlock.toggleClass('disabled', !power_user.sysprompt.enabled); |
| 54 | 59 | } |
| 55 | 60 | |
| 61 | +function enableSystemPromptCallback() { | |
| 62 | + power_user.sysprompt.enabled = true; | |
| 63 | + $enabled.prop('checked', true); | |
| 64 | + toggleSyspromptDisabledControls(); | |
| 65 | + saveSettingsDebounced(); | |
| 66 | + return ''; | |
| 67 | +} | |
| 68 | + | |
| 69 | +function disableSystemPromptCallback() { | |
| 70 | + power_user.sysprompt.enabled = false; | |
| 71 | + $enabled.prop('checked', false); | |
| 72 | + toggleSyspromptDisabledControls(); | |
| 73 | + saveSettingsDebounced(); | |
| 74 | + return ''; | |
| 75 | +} | |
| 76 | + | |
| 77 | +function toggleSystemPromptCallback(_args, state) { | |
| 78 | + if (!state || typeof state !== 'string') { | |
| 79 | + return String(power_user.sysprompt.enabled); | |
| 80 | + } | |
| 81 | + | |
| 82 | + const newState = isTrueBoolean(state); | |
| 83 | + newState ? enableSystemPromptCallback() : disableSystemPromptCallback(); | |
| 84 | + return String(power_user.sysprompt.enabled); | |
| 85 | +} | |
| 86 | + | |
| 87 | +function selectSystemPromptCallback(args, name) { | |
| 88 | + if (!power_user.sysprompt.enabled && !isTrueBoolean(args.forceGet)) { | |
| 89 | + return ''; | |
| 90 | + } | |
| 91 | + | |
| 92 | + if (!name) { | |
| 93 | + return power_user.sysprompt.name; | |
| 94 | + } | |
| 95 | + | |
| 96 | + const quiet = isTrueBoolean(args?.quiet); | |
| 97 | + const instructNames = system_prompts.map(preset => preset.name); | |
| 98 | + const fuse = new Fuse(instructNames); | |
| 99 | + const result = fuse.search(name); | |
| 100 | + | |
| 101 | + if (result.length === 0) { | |
| 102 | + !quiet && toastr.warning(`System prompt "${name}" not found`); | |
| 103 | + return ''; | |
| 104 | + } | |
| 105 | + | |
| 106 | + const foundName = result[0].item; | |
| 107 | + $select.val(foundName).trigger('input'); | |
| 108 | + !quiet && toastr.success(`System prompt "${foundName}" selected`); | |
| 109 | + return foundName; | |
| 110 | +} | |
| 111 | + | |
| 56 | 112 | jQuery(function () { |
| 57 | 113 | $enabled.on('input', function () { |
| 58 | 114 | power_user.sysprompt.enabled = !!$(this).prop('checked'); |
| @@ -61,6 +117,10 @@ jQuery(function () { | ||
| 61 | 117 | }); |
| 62 | 118 | |
| 63 | 119 | $select.on('input', async function () { |
| 120 | + if (!power_user.sysprompt.enabled) { | |
| 121 | + $enabled.prop('checked', true).trigger('input'); | |
| 122 | + } | |
| 123 | + | |
| 64 | 124 | const name = String($(this).val()); |
| 65 | 125 | const prompt = system_prompts.find(p => p.name === name); |
| 66 | 126 | if (prompt) { |
| @@ -79,4 +139,73 @@ jQuery(function () { | ||
| 79 | 139 | power_user.sysprompt.content = String($(this).val()); |
| 80 | 140 | saveSettingsDebounced(); |
| 81 | 141 | }); |
| 142 | + | |
| 143 | + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | |
| 144 | + name: 'sysprompt', | |
| 145 | + aliases: ['system-prompt'], | |
| 146 | + callback: selectSystemPromptCallback, | |
| 147 | + returns: 'current prompt name', | |
| 148 | + namedArgumentList: [ | |
| 149 | + SlashCommandNamedArgument.fromProps({ | |
| 150 | + name: 'quiet', | |
| 151 | + description: 'Suppress the toast message on prompt change', | |
| 152 | + typeList: [ARGUMENT_TYPE.BOOLEAN], | |
| 153 | + defaultValue: 'false', | |
| 154 | + enumList: commonEnumProviders.boolean('trueFalse')(), | |
| 155 | + }), | |
| 156 | + SlashCommandNamedArgument.fromProps({ | |
| 157 | + name: 'forceGet', | |
| 158 | + description: 'Force getting a name even if system prompt is disabled', | |
| 159 | + typeList: [ARGUMENT_TYPE.BOOLEAN], | |
| 160 | + defaultValue: 'false', | |
| 161 | + enumList: commonEnumProviders.boolean('trueFalse')(), | |
| 162 | + }), | |
| 163 | + ], | |
| 164 | + unnamedArgumentList: [ | |
| 165 | + SlashCommandArgument.fromProps({ | |
| 166 | + description: 'system prompt name', | |
| 167 | + typeList: [ARGUMENT_TYPE.STRING], | |
| 168 | + enumProvider: () => system_prompts.map(x => new SlashCommandEnumValue(x.name, null, enumTypes.enum, enumIcons.preset)), | |
| 169 | + }), | |
| 170 | + ], | |
| 171 | + helpString: ` | |
| 172 | + <div> | |
| 173 | + Selects a system prompt by name. Enables the use of system prompt if not already enabled. | |
| 174 | + Gets the current system prompt if no name is provided and sysprompt is enabled or <code>forceGet=true</code> is passed. | |
| 175 | + </div> | |
| 176 | + <div> | |
| 177 | + <strong>Example:</strong> | |
| 178 | + <ul> | |
| 179 | + <li> | |
| 180 | + <pre><code class="language-stscript">/sysprompt </code></pre> | |
| 181 | + </li> | |
| 182 | + </ul> | |
| 183 | + </div> | |
| 184 | + `, | |
| 185 | + })); | |
| 186 | + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | |
| 187 | + name: 'sysprompt-on', | |
| 188 | + aliases: ['sysprompt-enable'], | |
| 189 | + callback: enableSystemPromptCallback, | |
| 190 | + helpString: 'Enables system prompt.', | |
| 191 | + })); | |
| 192 | + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | |
| 193 | + name: 'sysprompt-off', | |
| 194 | + aliases: ['sysprompt-disable'], | |
| 195 | + callback: disableSystemPromptCallback, | |
| 196 | + helpString: 'Disables system prompt', | |
| 197 | + })); | |
| 198 | + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ | |
| 199 | + name: 'sysprompt-state', | |
| 200 | + aliases: ['sysprompt-toggle'], | |
| 201 | + helpString: 'Gets the current system prompt state. If an argument is provided, it will set the system prompt state.', | |
| 202 | + unnamedArgumentList: [ | |
| 203 | + SlashCommandArgument.fromProps({ | |
| 204 | + description: 'system prompt state', | |
| 205 | + typeList: [ARGUMENT_TYPE.BOOLEAN], | |
| 206 | + enumList: commonEnumProviders.boolean('trueFalse')(), | |
| 207 | + }), | |
| 208 | + ], | |
| 209 | + callback: toggleSystemPromptCallback, | |
| 210 | + })); | |
| 82 | 211 | }); |