2024-09-07 21:33:31 +03:00
import { event _types , eventSource , main _api , saveSettingsDebounced } from '../../../script.js' ;
2024-09-07 00:23:42 +03:00
import { extension _settings , renderExtensionTemplateAsync } from '../../extensions.js' ;
import { callGenericPopup , Popup , POPUP _TYPE } from '../../popup.js' ;
2024-09-07 13:58:46 +03:00
import { SlashCommand } from '../../slash-commands/SlashCommand.js' ;
2024-09-08 13:31:32 +03:00
import { SlashCommandAbortController } from '../../slash-commands/SlashCommandAbortController.js' ;
2024-09-07 21:33:31 +03:00
import { ARGUMENT _TYPE , SlashCommandArgument , SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js' ;
import { commonEnumProviders , enumIcons } from '../../slash-commands/SlashCommandCommonEnumsProvider.js' ;
2024-09-08 13:31:32 +03:00
import { SlashCommandDebugController } from '../../slash-commands/SlashCommandDebugController.js' ;
2024-09-07 13:58:46 +03:00
import { enumTypes , SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js' ;
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js' ;
2024-09-08 13:31:32 +03:00
import { SlashCommandScope } from '../../slash-commands/SlashCommandScope.js' ;
2024-09-07 21:33:31 +03:00
import { collapseSpaces , getUniqueName , isFalseBoolean , uuidv4 } from '../../utils.js' ;
2024-09-07 00:23:42 +03:00
const MODULE _NAME = 'connection-manager' ;
2024-09-07 13:58:46 +03:00
const NONE = '<None>' ;
2024-09-07 00:23:42 +03:00
const DEFAULT _SETTINGS = {
profiles : [ ] ,
selectedProfile : null ,
} ;
2024-09-19 23:12:33 +03:00
const CC _COMMANDS = [
2024-09-07 00:23:42 +03:00
'api' ,
'preset' ,
2024-09-19 23:12:33 +03:00
// Do not fix; CC needs to set the API twice because it could be overridden by the preset
'api' ,
2024-09-07 13:24:56 +03:00
'api-url' ,
2024-09-07 00:23:42 +03:00
'model' ,
'proxy' ,
] ;
const TC _COMMANDS = [
2024-09-19 23:12:33 +03:00
'api' ,
'preset' ,
'api-url' ,
'model' ,
2024-09-17 12:14:13 +00:00
'sysprompt' ,
'sysprompt-state' ,
2024-09-07 00:23:42 +03:00
'instruct' ,
'context' ,
'instruct-state' ,
'tokenizer' ,
] ;
const FANCY _NAMES = {
'api' : 'API' ,
2024-09-07 13:24:56 +03:00
'api-url' : 'Server URL' ,
2024-09-07 00:23:42 +03:00
'preset' : 'Settings Preset' ,
'model' : 'Model' ,
'proxy' : 'Proxy Preset' ,
2024-09-17 12:14:13 +00:00
'sysprompt-state' : 'Use System Prompt' ,
'sysprompt' : 'System Prompt Name' ,
2024-09-07 00:23:42 +03:00
'instruct-state' : 'Instruct Mode' ,
'instruct' : 'Instruct Template' ,
'context' : 'Context Template' ,
'tokenizer' : 'Tokenizer' ,
} ;
2024-09-07 23:53:22 +03:00
/ * *
* A wrapper for the connection manager spinner .
* /
class ConnectionManagerSpinner {
/ * *
* @ type { AbortController [ ] }
* /
static abortControllers = [ ] ;
/** @type {HTMLElement} */
spinnerElement ;
/** @type {AbortController} */
abortController = new AbortController ( ) ;
constructor ( ) {
// @ts-ignore
this . spinnerElement = document . getElementById ( 'connection_profile_spinner' ) ;
2024-09-08 01:19:52 +03:00
this . abortController = new AbortController ( ) ;
2024-09-07 23:53:22 +03:00
}
start ( ) {
ConnectionManagerSpinner . abortControllers . push ( this . abortController ) ;
this . spinnerElement . classList . remove ( 'hidden' ) ;
}
stop ( ) {
this . spinnerElement . classList . add ( 'hidden' ) ;
}
isAborted ( ) {
return this . abortController . signal . aborted ;
}
static abort ( ) {
for ( const controller of ConnectionManagerSpinner . abortControllers ) {
controller . abort ( ) ;
}
ConnectionManagerSpinner . abortControllers = [ ] ;
}
}
2024-09-08 13:31:32 +03:00
/ * *
* Get named arguments for the command callback .
* @ param { object } [ args ] Additional named arguments
* @ returns { object } Named arguments
* /
function getNamedArguments ( args = { } ) {
// None of the commands here use underscored args, but better safe than sorry
return {
_scope : new SlashCommandScope ( ) ,
_abortController : new SlashCommandAbortController ( ) ,
_debugController : new SlashCommandDebugController ( ) ,
_parserFlags : { } ,
_hasUnnamedArgument : false ,
quiet : 'true' ,
... args ,
} ;
}
2024-09-07 13:58:46 +03:00
/** @type {() => SlashCommandEnumValue[]} */
const profilesProvider = ( ) => [
2024-09-07 21:33:31 +03:00
new SlashCommandEnumValue ( NONE ) ,
2024-09-07 21:08:37 +03:00
... extension _settings . connectionManager . profiles . map ( p => new SlashCommandEnumValue ( p . name , null , enumTypes . name , enumIcons . server ) ) ,
2024-09-07 13:58:46 +03:00
] ;
2024-09-07 00:23:42 +03:00
/ * *
* @ typedef { Object } ConnectionProfile
* @ property { string } id Unique identifier
* @ property { string } mode Mode of the connection profile
* @ property { string } [ name ] Name of the connection profile
* @ property { string } [ api ] API
* @ property { string } [ preset ] Settings Preset
* @ property { string } [ model ] Model
* @ property { string } [ proxy ] Proxy Preset
* @ property { string } [ instruct ] Instruct Template
* @ property { string } [ context ] Context Template
* @ property { string } [ instruct - state ] Instruct Mode
* @ property { string } [ tokenizer ] Tokenizer
* /
2024-09-07 17:13:32 +03:00
/ * *
* Finds the best match for the search value .
* @ param { string } value Search value
* @ returns { ConnectionProfile | null } Best match or null
* /
function findProfileByName ( value ) {
// Try to find exact match
const profile = extension _settings . connectionManager . profiles . find ( p => p . name === value ) ;
if ( profile ) {
return profile ;
}
// Try to find fuzzy match
const fuse = new Fuse ( extension _settings . connectionManager . profiles , { keys : [ 'name' ] } ) ;
const results = fuse . search ( value ) ;
if ( results . length === 0 ) {
return null ;
}
const bestMatch = results [ 0 ] ;
return bestMatch . item ;
}
2024-09-07 00:23:42 +03:00
/ * *
* Reads the connection profile from the commands .
* @ param { string } mode Mode of the connection profile
* @ param { ConnectionProfile } profile Connection profile
* @ param { boolean } [ cleanUp ] Whether to clean up the profile
* /
async function readProfileFromCommands ( mode , profile , cleanUp = false ) {
const commands = mode === 'cc' ? CC _COMMANDS : TC _COMMANDS ;
const opposingCommands = mode === 'cc' ? TC _COMMANDS : CC _COMMANDS ;
for ( const command of commands ) {
try {
2024-09-08 13:31:32 +03:00
const args = getNamedArguments ( ) ;
const result = await SlashCommandParser . commands [ command ] . callback ( args , '' ) ;
if ( result ) {
profile [ command ] = result ;
2024-09-07 00:23:42 +03:00
continue ;
}
} catch ( error ) {
2024-09-08 13:32:56 +03:00
console . error ( ` Failed to execute command: ${ command } ` , error ) ;
2024-09-07 00:23:42 +03:00
}
}
if ( cleanUp ) {
2024-09-17 12:14:13 +00:00
for ( const command of commands ) {
if ( command . endsWith ( '-state' ) && profile [ command ] === 'false' ) {
delete profile [ command . replace ( '-state' , '' ) ] ;
}
}
2024-09-07 00:23:42 +03:00
for ( const command of opposingCommands ) {
if ( commands . includes ( command ) ) {
continue ;
}
delete profile [ command ] ;
}
}
}
/ * *
* Creates a new connection profile .
2024-09-07 14:56:30 +03:00
* @ param { string } [ forceName ] Name of the connection profile
2024-09-07 00:23:42 +03:00
* @ returns { Promise < ConnectionProfile > } Created connection profile
* /
2024-09-07 14:56:30 +03:00
async function createConnectionProfile ( forceName = null ) {
2024-09-07 00:23:42 +03:00
const mode = main _api === 'openai' ? 'cc' : 'tc' ;
2024-09-07 01:12:53 +03:00
const id = uuidv4 ( ) ;
2024-09-07 00:23:42 +03:00
const profile = {
id ,
mode ,
} ;
await readProfileFromCommands ( mode , profile ) ;
const profileForDisplay = makeFancyProfile ( profile ) ;
const template = await renderExtensionTemplateAsync ( MODULE _NAME , 'profile' , { profile : profileForDisplay } ) ;
2024-09-07 21:21:46 +03:00
const isNameTaken = ( n ) => extension _settings . connectionManager . profiles . some ( p => p . name === n ) ;
const suggestedName = getUniqueName ( collapseSpaces ( ` ${ profile . api ? ? '' } ${ profile . model ? ? '' } - ${ profile . preset ? ? '' } ` ) , isNameTaken ) ;
2024-09-07 14:56:30 +03:00
const name = forceName ? ? await callGenericPopup ( template , POPUP _TYPE . INPUT , suggestedName , { rows : 2 } ) ;
2024-09-07 00:23:42 +03:00
if ( ! name ) {
2024-09-07 00:27:52 +03:00
return null ;
2024-09-07 00:23:42 +03:00
}
2024-09-07 21:33:31 +03:00
if ( isNameTaken ( name ) || name === NONE ) {
2024-09-07 21:21:46 +03:00
toastr . error ( 'A profile with the same name already exists.' ) ;
return null ;
}
2024-09-07 00:23:42 +03:00
profile . name = name ;
return profile ;
}
/ * *
* Deletes the selected connection profile .
* @ returns { Promise < void > }
* /
async function deleteConnectionProfile ( ) {
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
if ( ! selectedProfile ) {
return ;
}
const index = extension _settings . connectionManager . profiles . findIndex ( p => p . id === selectedProfile ) ;
if ( index === - 1 ) {
return ;
}
2024-09-07 01:18:35 +03:00
const name = extension _settings . connectionManager . profiles [ index ] . name ;
const confirm = await Popup . show . confirm ( 'Are you sure you want to delete the selected profile?' , name ) ;
2024-09-07 00:23:42 +03:00
if ( ! confirm ) {
return ;
}
extension _settings . connectionManager . profiles . splice ( index , 1 ) ;
extension _settings . connectionManager . selectedProfile = null ;
saveSettingsDebounced ( ) ;
}
/ * *
* Formats the connection profile for display .
* @ param { ConnectionProfile } profile Connection profile
* @ returns { Object } Fancy profile
* /
function makeFancyProfile ( profile ) {
return Object . entries ( FANCY _NAMES ) . reduce ( ( acc , [ key , value ] ) => {
if ( ! profile [ key ] ) return acc ;
acc [ value ] = profile [ key ] ;
return acc ;
} , { } ) ;
}
/ * *
* Applies the connection profile .
* @ param { ConnectionProfile } profile Connection profile
* @ returns { Promise < void > }
* /
async function applyConnectionProfile ( profile ) {
if ( ! profile ) {
return ;
}
2024-09-07 23:53:22 +03:00
// Abort any ongoing profile application
ConnectionManagerSpinner . abort ( ) ;
2024-09-07 00:23:42 +03:00
const mode = profile . mode ;
const commands = mode === 'cc' ? CC _COMMANDS : TC _COMMANDS ;
2024-09-07 23:53:22 +03:00
const spinner = new ConnectionManagerSpinner ( ) ;
spinner . start ( ) ;
2024-09-07 00:23:42 +03:00
for ( const command of commands ) {
2024-09-07 23:53:22 +03:00
if ( spinner . isAborted ( ) ) {
throw new Error ( 'Profile application aborted' ) ;
}
2024-09-07 00:23:42 +03:00
const argument = profile [ command ] ;
if ( ! argument ) {
continue ;
}
try {
2024-09-08 13:31:32 +03:00
const args = getNamedArguments ( ) ;
await SlashCommandParser . commands [ command ] . callback ( args , argument ) ;
2024-09-07 00:23:42 +03:00
} catch ( error ) {
2024-09-08 13:31:32 +03:00
console . error ( ` Failed to execute command: ${ command } ${ argument } ` , error ) ;
2024-09-07 00:23:42 +03:00
}
}
2024-09-07 23:53:22 +03:00
spinner . stop ( ) ;
2024-09-07 00:23:42 +03:00
}
/ * *
* Updates the selected connection profile .
2024-09-07 00:30:47 +03:00
* @ param { ConnectionProfile } profile Connection profile
2024-09-07 00:23:42 +03:00
* @ returns { Promise < void > }
* /
2024-09-07 00:30:47 +03:00
async function updateConnectionProfile ( profile ) {
2024-09-07 00:23:42 +03:00
profile . mode = main _api === 'openai' ? 'cc' : 'tc' ;
await readProfileFromCommands ( profile . mode , profile , true ) ;
}
/ * *
* Renders the connection profile details .
* @ param { HTMLSelectElement } profiles Select element containing connection profiles
* /
function renderConnectionProfiles ( profiles ) {
profiles . innerHTML = '' ;
const noneOption = document . createElement ( 'option' ) ;
noneOption . value = '' ;
2024-09-07 13:58:46 +03:00
noneOption . textContent = NONE ;
2024-09-07 00:23:42 +03:00
noneOption . selected = ! extension _settings . connectionManager . selectedProfile ;
profiles . appendChild ( noneOption ) ;
2024-09-23 20:19:18 +03:00
for ( const profile of extension _settings . connectionManager . profiles . sort ( ( a , b ) => a . name . localeCompare ( b . name ) ) ) {
2024-09-07 00:23:42 +03:00
const option = document . createElement ( 'option' ) ;
option . value = profile . id ;
option . textContent = profile . name ;
option . selected = profile . id === extension _settings . connectionManager . selectedProfile ;
profiles . appendChild ( option ) ;
}
}
/ * *
* Renders the content of the details element .
* @ param { HTMLElement } detailsContent Content element of the details
* /
2024-09-08 01:19:52 +03:00
async function renderDetailsContent ( detailsContent ) {
2024-09-07 00:23:42 +03:00
detailsContent . innerHTML = '' ;
2024-09-08 01:19:52 +03:00
if ( detailsContent . classList . contains ( 'hidden' ) ) {
return ;
}
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === selectedProfile ) ;
if ( profile ) {
const profileForDisplay = makeFancyProfile ( profile ) ;
const template = await renderExtensionTemplateAsync ( MODULE _NAME , 'view' , { profile : profileForDisplay } ) ;
detailsContent . innerHTML = template ;
} else {
detailsContent . textContent = 'No profile selected' ;
2024-09-07 00:23:42 +03:00
}
}
( async function ( ) {
extension _settings . connectionManager = extension _settings . connectionManager || structuredClone ( DEFAULT _SETTINGS ) ;
for ( const key of Object . keys ( DEFAULT _SETTINGS ) ) {
if ( extension _settings . connectionManager [ key ] === undefined ) {
extension _settings . connectionManager [ key ] = DEFAULT _SETTINGS [ key ] ;
}
}
const container = document . getElementById ( 'rm_api_block' ) ;
const settings = await renderExtensionTemplateAsync ( MODULE _NAME , 'settings' ) ;
container . insertAdjacentHTML ( 'afterbegin' , settings ) ;
/** @type {HTMLSelectElement} */
// @ts-ignore
const profiles = document . getElementById ( 'connection_profiles' ) ;
renderConnectionProfiles ( profiles ) ;
2024-09-08 01:18:44 +02:00
function toggleProfileSpecificButtons ( ) {
const profileId = extension _settings . connectionManager . selectedProfile ;
const profileSpecificButtons = [ 'update_connection_profile' , 'reload_connection_profile' , 'delete_connection_profile' ] ;
profileSpecificButtons . forEach ( id => document . getElementById ( id ) . classList . toggle ( 'disabled' , ! profileId ) ) ;
}
toggleProfileSpecificButtons ( ) ;
2024-09-07 00:23:42 +03:00
profiles . addEventListener ( 'change' , async function ( ) {
const selectedProfile = profiles . selectedOptions [ 0 ] ;
if ( ! selectedProfile ) {
2024-09-07 21:33:31 +03:00
// Safety net for preventing the command getting stuck
await eventSource . emit ( event _types . CONNECTION _PROFILE _LOADED , NONE ) ;
2024-09-07 00:23:42 +03:00
return ;
}
const profileId = selectedProfile . value ;
extension _settings . connectionManager . selectedProfile = profileId ;
saveSettingsDebounced ( ) ;
2024-09-08 01:19:52 +03:00
await renderDetailsContent ( detailsContent ) ;
2024-09-07 00:23:42 +03:00
2024-09-08 01:18:44 +02:00
toggleProfileSpecificButtons ( ) ;
2024-09-07 21:08:37 +03:00
// None option selected
if ( ! profileId ) {
2024-09-07 21:33:31 +03:00
await eventSource . emit ( event _types . CONNECTION _PROFILE _LOADED , NONE ) ;
2024-09-07 21:08:37 +03:00
return ;
}
2024-09-07 00:23:42 +03:00
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === profileId ) ;
if ( ! profile ) {
console . log ( ` Profile not found: ${ profileId } ` ) ;
return ;
}
await applyConnectionProfile ( profile ) ;
2024-09-07 21:33:31 +03:00
await eventSource . emit ( event _types . CONNECTION _PROFILE _LOADED , profile . name ) ;
2024-09-07 00:23:42 +03:00
} ) ;
const reloadButton = document . getElementById ( 'reload_connection_profile' ) ;
reloadButton . addEventListener ( 'click' , async ( ) => {
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === selectedProfile ) ;
if ( ! profile ) {
console . log ( 'No profile selected' ) ;
return ;
}
await applyConnectionProfile ( profile ) ;
2024-09-08 01:19:52 +03:00
await renderDetailsContent ( detailsContent ) ;
2024-09-07 21:33:31 +03:00
await eventSource . emit ( event _types . CONNECTION _PROFILE _LOADED , profile . name ) ;
2024-09-07 00:23:42 +03:00
toastr . success ( 'Connection profile reloaded' , '' , { timeOut : 1500 } ) ;
} ) ;
const createButton = document . getElementById ( 'create_connection_profile' ) ;
createButton . addEventListener ( 'click' , async ( ) => {
const profile = await createConnectionProfile ( ) ;
2024-09-07 00:27:52 +03:00
if ( ! profile ) {
return ;
}
2024-09-07 00:23:42 +03:00
extension _settings . connectionManager . profiles . push ( profile ) ;
extension _settings . connectionManager . selectedProfile = profile . id ;
saveSettingsDebounced ( ) ;
renderConnectionProfiles ( profiles ) ;
2024-09-08 01:19:52 +03:00
await renderDetailsContent ( detailsContent ) ;
2024-09-07 21:33:31 +03:00
await eventSource . emit ( event _types . CONNECTION _PROFILE _LOADED , profile . name ) ;
2024-09-07 00:23:42 +03:00
} ) ;
const updateButton = document . getElementById ( 'update_connection_profile' ) ;
updateButton . addEventListener ( 'click' , async ( ) => {
2024-09-07 00:30:47 +03:00
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === selectedProfile ) ;
if ( ! profile ) {
console . log ( 'No profile selected' ) ;
return ;
}
await updateConnectionProfile ( profile ) ;
2024-09-08 01:19:52 +03:00
await renderDetailsContent ( detailsContent ) ;
2024-09-07 00:23:42 +03:00
saveSettingsDebounced ( ) ;
2024-09-07 21:33:31 +03:00
await eventSource . emit ( event _types . CONNECTION _PROFILE _LOADED , profile . name ) ;
2024-09-07 00:23:42 +03:00
toastr . success ( 'Connection profile updated' , '' , { timeOut : 1500 } ) ;
} ) ;
const deleteButton = document . getElementById ( 'delete_connection_profile' ) ;
deleteButton . addEventListener ( 'click' , async ( ) => {
await deleteConnectionProfile ( ) ;
renderConnectionProfiles ( profiles ) ;
2024-09-08 01:19:52 +03:00
await renderDetailsContent ( detailsContent ) ;
2024-09-07 21:33:31 +03:00
await eventSource . emit ( event _types . CONNECTION _PROFILE _LOADED , NONE ) ;
2024-09-07 00:23:42 +03:00
} ) ;
2024-09-23 20:19:18 +03:00
const renameButton = document . getElementById ( 'rename_connection_profile' ) ;
renameButton . addEventListener ( 'click' , async ( ) => {
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === selectedProfile ) ;
if ( ! profile ) {
console . log ( 'No profile selected' ) ;
return ;
}
const newName = await Popup . show . input ( 'Enter a new name' , null , profile . name , { rows : 2 } ) ;
if ( ! newName ) {
return ;
}
if ( extension _settings . connectionManager . profiles . some ( p => p . name === newName ) ) {
toastr . error ( 'A profile with the same name already exists.' ) ;
return ;
}
profile . name = newName ;
saveSettingsDebounced ( ) ;
renderConnectionProfiles ( profiles ) ;
toastr . success ( 'Connection profile renamed' , '' , { timeOut : 1500 } ) ;
} ) ;
2024-09-08 01:19:52 +03:00
/** @type {HTMLElement} */
const viewDetails = document . getElementById ( 'view_connection_profile' ) ;
2024-09-07 00:23:42 +03:00
const detailsContent = document . getElementById ( 'connection_profile_details_content' ) ;
2024-09-08 01:19:52 +03:00
viewDetails . addEventListener ( 'click' , async ( ) => {
viewDetails . classList . toggle ( 'active' ) ;
detailsContent . classList . toggle ( 'hidden' ) ;
await renderDetailsContent ( detailsContent ) ;
} ) ;
2024-09-07 13:58:46 +03:00
SlashCommandParser . addCommandObject ( SlashCommand . fromProps ( {
name : 'profile' ,
helpString : 'Switch to a connection profile or return the name of the current profile in no argument is provided. Use <code><None></code> to switch to no profile.' ,
2024-09-07 14:56:30 +03:00
returns : 'name of the profile' ,
2024-09-07 13:58:46 +03:00
unnamedArgumentList : [
SlashCommandArgument . fromProps ( {
description : 'Name of the connection profile' ,
enumProvider : profilesProvider ,
isRequired : false ,
} ) ,
] ,
2024-09-07 21:33:31 +03:00
namedArgumentList : [
SlashCommandNamedArgument . fromProps ( {
name : 'await' ,
description : 'Wait for the connection profile to be applied before returning.' ,
isRequired : false ,
typeList : [ ARGUMENT _TYPE . BOOLEAN ] ,
defaultValue : 'true' ,
enumList : commonEnumProviders . boolean ( 'trueFalse' ) ( ) ,
} ) ,
] ,
callback : async ( args , value ) => {
2024-09-07 13:58:46 +03:00
if ( ! value || typeof value !== 'string' ) {
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === selectedProfile ) ;
if ( ! profile ) {
return NONE ;
}
return profile . name ;
}
if ( value === NONE ) {
profiles . selectedIndex = 0 ;
profiles . dispatchEvent ( new Event ( 'change' ) ) ;
return NONE ;
}
2024-09-07 17:13:32 +03:00
const profile = findProfileByName ( value ) ;
2024-09-07 13:58:46 +03:00
2024-09-07 17:13:32 +03:00
if ( ! profile ) {
2024-09-07 13:58:46 +03:00
return '' ;
}
2024-09-07 21:33:31 +03:00
const shouldAwait = ! isFalseBoolean ( String ( args ? . await ) ) ;
const awaitPromise = new Promise ( ( resolve ) => eventSource . once ( event _types . CONNECTION _PROFILE _LOADED , resolve ) ) ;
2024-09-07 17:13:32 +03:00
profiles . selectedIndex = Array . from ( profiles . options ) . findIndex ( o => o . value === profile . id ) ;
2024-09-07 13:58:46 +03:00
profiles . dispatchEvent ( new Event ( 'change' ) ) ;
2024-09-07 17:13:32 +03:00
2024-09-07 21:33:31 +03:00
if ( shouldAwait ) {
await awaitPromise ;
}
2024-09-07 19:32:58 +02:00
return profile . name ;
2024-09-07 13:58:46 +03:00
} ,
} ) ) ;
2024-09-07 14:56:30 +03:00
SlashCommandParser . addCommandObject ( SlashCommand . fromProps ( {
name : 'profile-list' ,
helpString : 'List all connection profile names.' ,
returns : 'list of profile names' ,
callback : ( ) => JSON . stringify ( extension _settings . connectionManager . profiles . map ( p => p . name ) ) ,
} ) ) ;
SlashCommandParser . addCommandObject ( SlashCommand . fromProps ( {
name : 'profile-create' ,
returns : 'name of the new profile' ,
helpString : 'Create a new connection profile using the current settings.' ,
unnamedArgumentList : [
SlashCommandArgument . fromProps ( {
description : 'name of the new connection profile' ,
isRequired : true ,
typeList : [ ARGUMENT _TYPE . STRING ] ,
} ) ,
] ,
callback : async ( _args , name ) => {
if ( ! name || typeof name !== 'string' ) {
toastr . warning ( 'Please provide a name for the new connection profile.' ) ;
return '' ;
}
const profile = await createConnectionProfile ( name ) ;
if ( ! profile ) {
return '' ;
}
extension _settings . connectionManager . profiles . push ( profile ) ;
extension _settings . connectionManager . selectedProfile = profile . id ;
saveSettingsDebounced ( ) ;
renderConnectionProfiles ( profiles ) ;
2024-09-08 01:19:52 +03:00
await renderDetailsContent ( detailsContent ) ;
2024-09-07 14:56:30 +03:00
return profile . name ;
} ,
} ) ) ;
SlashCommandParser . addCommandObject ( SlashCommand . fromProps ( {
name : 'profile-update' ,
helpString : 'Update the selected connection profile.' ,
callback : async ( ) => {
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === selectedProfile ) ;
if ( ! profile ) {
2024-09-07 21:08:37 +03:00
toastr . warning ( 'No profile selected.' ) ;
2024-09-07 14:56:30 +03:00
return '' ;
}
await updateConnectionProfile ( profile ) ;
2024-09-08 01:19:52 +03:00
await renderDetailsContent ( detailsContent ) ;
2024-09-07 14:56:30 +03:00
saveSettingsDebounced ( ) ;
2024-09-07 21:08:37 +03:00
return profile . name ;
2024-09-07 14:56:30 +03:00
} ,
} ) ) ;
2024-09-07 17:13:32 +03:00
SlashCommandParser . addCommandObject ( SlashCommand . fromProps ( {
name : 'profile-get' ,
helpString : 'Get the details of the connection profile. Returns the selected profile if no argument is provided.' ,
returns : 'object of the selected profile' ,
unnamedArgumentList : [
SlashCommandArgument . fromProps ( {
description : 'Name of the connection profile' ,
enumProvider : profilesProvider ,
isRequired : false ,
} ) ,
] ,
callback : async ( _args , value ) => {
if ( ! value || typeof value !== 'string' ) {
const selectedProfile = extension _settings . connectionManager . selectedProfile ;
const profile = extension _settings . connectionManager . profiles . find ( p => p . id === selectedProfile ) ;
if ( ! profile ) {
return '' ;
}
return JSON . stringify ( profile ) ;
}
const profile = findProfileByName ( value ) ;
if ( ! profile ) {
return '' ;
}
return JSON . stringify ( profile ) ;
} ,
} ) ) ;
2024-09-07 00:23:42 +03:00
} ) ( ) ;