Add slash commands and connection profiles support

0bc6a572c6ca35a863fe2688911dabfee5a5056d

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

2 files changed, +139 -1Ignore whitespace
public/scripts/extensions/connection-manager/index.js+9 -0
@@ -33,6 +33,8 @@ const CC_COMMANDS = [
3333
34const TC_COMMANDS = [34const TC_COMMANDS = [
35 ...COMMON_COMMANDS,35 ...COMMON_COMMANDS,
36 'sysprompt',
37 'sysprompt-state',
36 'instruct',38 'instruct',
37 'context',39 'context',
38 'instruct-state',40 'instruct-state',
@@ -45,6 +47,8 @@ const FANCY_NAMES = {
45 'preset': 'Settings Preset',47 'preset': 'Settings Preset',
46 'model': 'Model',48 'model': 'Model',
47 'proxy': 'Proxy Preset',49 'proxy': 'Proxy Preset',
50 'sysprompt-state': 'Use System Prompt',
51 'sysprompt': 'System Prompt Name',
48 'instruct-state': 'Instruct Mode',52 'instruct-state': 'Instruct Mode',
49 'instruct': 'Instruct Template',53 'instruct': 'Instruct Template',
50 'context': 'Context Template',54 'context': 'Context Template',
@@ -180,6 +184,11 @@ async function readProfileFromCommands(mode, profile, cleanUp = false) {
180 }184 }
181185
182 if (cleanUp) {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 for (const command of opposingCommands) {192 for (const command of opposingCommands) {
184 if (commands.includes(command)) {193 if (commands.includes(command)) {
185 continue;194 continue;
public/scripts/sysprompt.js+130 -1
@@ -1,6 +1,11 @@
1import { saveSettingsDebounced } from '../script.js';1import { saveSettingsDebounced } from '../script.js';
2import { power_user } from './power-user.js';2import { power_user } from './power-user.js';
3import { resetScrollHeight } from './utils.js';3import { SlashCommand } from './slash-commands/SlashCommand.js';
4import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from './slash-commands/SlashCommandArgument.js';
5import { commonEnumProviders, enumIcons } from './slash-commands/SlashCommandCommonEnumsProvider.js';
6import { enumTypes, SlashCommandEnumValue } from './slash-commands/SlashCommandEnumValue.js';
7import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
8import { isTrueBoolean, resetScrollHeight } from './utils.js';
49
5export let system_prompts = [];10export let system_prompts = [];
611
@@ -53,6 +58,57 @@ function toggleSyspromptDisabledControls() {
53 $contentBlock.toggleClass('disabled', !power_user.sysprompt.enabled);58 $contentBlock.toggleClass('disabled', !power_user.sysprompt.enabled);
54}59}
5560
61function enableSystemPromptCallback() {
62 power_user.sysprompt.enabled = true;
63 $enabled.prop('checked', true);
64 toggleSyspromptDisabledControls();
65 saveSettingsDebounced();
66 return '';
67}
68
69function disableSystemPromptCallback() {
70 power_user.sysprompt.enabled = false;
71 $enabled.prop('checked', false);
72 toggleSyspromptDisabledControls();
73 saveSettingsDebounced();
74 return '';
75}
76
77function 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
87function 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
56jQuery(function () {112jQuery(function () {
57 $enabled.on('input', function () {113 $enabled.on('input', function () {
58 power_user.sysprompt.enabled = !!$(this).prop('checked');114 power_user.sysprompt.enabled = !!$(this).prop('checked');
@@ -61,6 +117,10 @@ jQuery(function () {
61 });117 });
62118
63 $select.on('input', async function () {119 $select.on('input', async function () {
120 if (!power_user.sysprompt.enabled) {
121 $enabled.prop('checked', true).trigger('input');
122 }
123
64 const name = String($(this).val());124 const name = String($(this).val());
65 const prompt = system_prompts.find(p => p.name === name);125 const prompt = system_prompts.find(p => p.name === name);
66 if (prompt) {126 if (prompt) {
@@ -79,4 +139,73 @@ jQuery(function () {
79 power_user.sysprompt.content = String($(this).val());139 power_user.sysprompt.content = String($(this).val());
80 saveSettingsDebounced();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});