2023-12-02 19:04:51 +01:00
import { callPopup , getRequestHeaders } from '../script.js' ;
2023-07-20 19:32:15 +02:00
export const SECRET _KEYS = {
HORDE : 'api_key_horde' ,
2023-08-02 09:31:17 +02:00
MANCER : 'api_key_mancer' ,
2024-05-03 00:40:40 +02:00
VLLM : 'api_key_vllm' ,
2023-09-28 18:10:00 +02:00
APHRODITE : 'api_key_aphrodite' ,
2023-11-17 06:32:49 +01:00
TABBY : 'api_key_tabby' ,
2023-07-20 19:32:15 +02:00
OPENAI : 'api_key_openai' ,
NOVEL : 'api_key_novel' ,
CLAUDE : 'api_key_claude' ,
OPENROUTER : 'api_key_openrouter' ,
SCALE : 'api_key_scale' ,
2023-08-19 17:20:42 +02:00
AI21 : 'api_key_ai21' ,
2023-08-20 12:55:37 +02:00
SCALE _COOKIE : 'scale_cookie' ,
2023-12-14 02:14:41 +01:00
MAKERSUITE : 'api_key_makersuite' ,
2023-11-13 23:16:41 +01:00
SERPAPI : 'api_key_serpapi' ,
2023-12-15 21:08:41 +01:00
MISTRALAI : 'api_key_mistralai' ,
2023-12-16 15:11:04 +01:00
TOGETHERAI : 'api_key_togetherai' ,
2024-01-24 13:59:27 +01:00
INFERMATICAI : 'api_key_infermaticai' ,
2024-03-07 10:55:08 +01:00
DREAMGEN : 'api_key_dreamgen' ,
2023-12-20 17:29:03 +01:00
CUSTOM : 'api_key_custom' ,
2024-02-07 18:28:34 +01:00
OOBA : 'api_key_ooba' ,
2024-03-12 20:10:25 +01:00
NOMICAI : 'api_key_nomicai' ,
2024-03-13 23:34:09 +01:00
KOBOLDCPP : 'api_key_koboldcpp' ,
2024-03-30 23:27:12 +01:00
LLAMACPP : 'api_key_llamacpp' ,
2024-04-01 23:20:17 +02:00
COHERE : 'api_key_cohere' ,
2024-04-19 23:09:38 +02:00
PERPLEXITY : 'api_key_perplexity' ,
2024-05-05 17:53:12 +02:00
GROQ : 'api_key_groq' ,
2024-05-22 00:37:51 +02:00
AZURE _TTS : 'api_key_azure_tts' ,
2024-06-27 15:06:11 +02:00
FEATHERLESS : 'api_key_featherless' ,
2024-06-27 23:51:09 +02:00
ZEROONEAI : 'api_key_01ai' ,
2024-06-28 17:17:27 +02:00
HUGGINGFACE : 'api_key_huggingface' ,
2024-07-04 21:36:17 +02:00
STABILITY : 'api_key_stability' ,
2024-08-08 06:08:03 +02:00
BLOCKENTROPY : 'api_key_blockentropy' ,
2024-08-13 19:29:33 +02:00
CUSTOM _OPENAI _TTS : 'api_key_custom_openai_tts' ,
2023-12-02 20:11:06 +01:00
} ;
2023-07-20 19:32:15 +02:00
const INPUT _MAP = {
[ SECRET _KEYS . HORDE ] : '#horde_api_key' ,
2023-08-02 09:31:17 +02:00
[ SECRET _KEYS . MANCER ] : '#api_key_mancer' ,
2023-07-20 19:32:15 +02:00
[ SECRET _KEYS . OPENAI ] : '#api_key_openai' ,
[ SECRET _KEYS . NOVEL ] : '#api_key_novel' ,
[ SECRET _KEYS . CLAUDE ] : '#api_key_claude' ,
2024-02-25 21:47:07 +01:00
[ SECRET _KEYS . OPENROUTER ] : '.api_key_openrouter' ,
2023-07-20 19:32:15 +02:00
[ SECRET _KEYS . SCALE ] : '#api_key_scale' ,
2023-08-19 17:20:42 +02:00
[ SECRET _KEYS . AI21 ] : '#api_key_ai21' ,
2023-08-20 12:55:37 +02:00
[ SECRET _KEYS . SCALE _COOKIE ] : '#scale_cookie' ,
2023-12-14 02:14:41 +01:00
[ SECRET _KEYS . MAKERSUITE ] : '#api_key_makersuite' ,
2024-05-03 00:40:40 +02:00
[ SECRET _KEYS . VLLM ] : '#api_key_vllm' ,
2023-09-28 18:10:00 +02:00
[ SECRET _KEYS . APHRODITE ] : '#api_key_aphrodite' ,
2023-12-02 21:06:57 +01:00
[ SECRET _KEYS . TABBY ] : '#api_key_tabby' ,
2023-12-15 21:08:41 +01:00
[ SECRET _KEYS . MISTRALAI ] : '#api_key_mistralai' ,
2023-12-20 17:29:03 +01:00
[ SECRET _KEYS . CUSTOM ] : '#api_key_custom' ,
2023-12-16 15:11:04 +01:00
[ SECRET _KEYS . TOGETHERAI ] : '#api_key_togetherai' ,
2024-02-07 05:00:16 +01:00
[ SECRET _KEYS . OOBA ] : '#api_key_ooba' ,
2024-01-24 13:59:27 +01:00
[ SECRET _KEYS . INFERMATICAI ] : '#api_key_infermaticai' ,
2024-03-07 10:55:08 +01:00
[ SECRET _KEYS . DREAMGEN ] : '#api_key_dreamgen' ,
2024-03-12 20:10:25 +01:00
[ SECRET _KEYS . NOMICAI ] : '#api_key_nomicai' ,
2024-03-13 23:34:09 +01:00
[ SECRET _KEYS . KOBOLDCPP ] : '#api_key_koboldcpp' ,
2024-03-30 23:27:12 +01:00
[ SECRET _KEYS . LLAMACPP ] : '#api_key_llamacpp' ,
2024-04-01 23:20:17 +02:00
[ SECRET _KEYS . COHERE ] : '#api_key_cohere' ,
2024-04-19 23:09:38 +02:00
[ SECRET _KEYS . PERPLEXITY ] : '#api_key_perplexity' ,
2024-05-05 17:53:12 +02:00
[ SECRET _KEYS . GROQ ] : '#api_key_groq' ,
2024-06-28 14:20:15 +02:00
[ SECRET _KEYS . FEATHERLESS ] : '#api_key_featherless' ,
2024-06-27 23:51:09 +02:00
[ SECRET _KEYS . ZEROONEAI ] : '#api_key_01ai' ,
2024-06-28 17:17:27 +02:00
[ SECRET _KEYS . HUGGINGFACE ] : '#api_key_huggingface' ,
2024-08-08 06:08:03 +02:00
[ SECRET _KEYS . BLOCKENTROPY ] : '#api_key_blockentropy' ,
2023-12-02 20:11:06 +01:00
} ;
2023-07-20 19:32:15 +02:00
async function clearSecret ( ) {
const key = $ ( this ) . data ( 'key' ) ;
await writeSecret ( key , '' ) ;
secret _state [ key ] = false ;
updateSecretDisplay ( ) ;
2024-03-12 20:10:25 +01:00
$ ( INPUT _MAP [ key ] ) . val ( '' ) . trigger ( 'input' ) ;
2023-07-20 19:32:15 +02:00
$ ( '#main_api' ) . trigger ( 'change' ) ;
}
2024-04-24 16:07:42 +02:00
export function updateSecretDisplay ( ) {
2023-07-20 19:32:15 +02:00
for ( const [ secret _key , input _selector ] of Object . entries ( INPUT _MAP ) ) {
const validSecret = ! ! secret _state [ secret _key ] ;
2024-04-26 21:57:42 +02:00
const placeholder = $ ( '#viewSecrets' ) . attr ( validSecret ? 'key_saved_text' : 'missing_key_text' ) ;
2023-07-20 19:32:15 +02:00
$ ( input _selector ) . attr ( 'placeholder' , placeholder ) ;
}
}
async function viewSecrets ( ) {
2023-12-03 15:19:25 +01:00
const response = await fetch ( '/api/secrets/view' , {
2023-07-20 19:32:15 +02:00
method : 'POST' ,
headers : getRequestHeaders ( ) ,
} ) ;
if ( response . status == 403 ) {
2023-11-25 22:45:33 +01:00
callPopup ( '<h3>Forbidden</h3><p>To view your API keys here, set the value of allowKeysExposure to true in config.yaml file and restart the SillyTavern server.</p>' , 'text' ) ;
2023-07-20 19:32:15 +02:00
return ;
}
if ( ! response . ok ) {
return ;
}
$ ( '#dialogue_popup' ) . addClass ( 'wide_dialogue_popup' ) ;
const data = await response . json ( ) ;
const table = document . createElement ( 'table' ) ;
table . classList . add ( 'responsiveTable' ) ;
$ ( table ) . append ( '<thead><th>Key</th><th>Value</th></thead>' ) ;
for ( const [ key , value ] of Object . entries ( data ) ) {
$ ( table ) . append ( ` <tr><td> ${ DOMPurify . sanitize ( key ) } </td><td> ${ DOMPurify . sanitize ( value ) } </td></tr> ` ) ;
}
callPopup ( table . outerHTML , 'text' ) ;
}
export let secret _state = { } ;
export async function writeSecret ( key , value ) {
try {
2023-09-16 15:39:07 +02:00
const response = await fetch ( '/api/secrets/write' , {
2023-07-20 19:32:15 +02:00
method : 'POST' ,
headers : getRequestHeaders ( ) ,
body : JSON . stringify ( { key , value } ) ,
} ) ;
if ( response . ok ) {
const text = await response . text ( ) ;
if ( text == 'ok' ) {
2024-08-13 19:29:33 +02:00
secret _state [ key ] = ! ! value ;
2023-07-20 19:32:15 +02:00
updateSecretDisplay ( ) ;
}
}
} catch {
console . error ( 'Could not write secret value: ' , key ) ;
}
}
export async function readSecretState ( ) {
try {
2023-09-16 15:39:07 +02:00
const response = await fetch ( '/api/secrets/read' , {
2023-07-20 19:32:15 +02:00
method : 'POST' ,
headers : getRequestHeaders ( ) ,
} ) ;
if ( response . ok ) {
secret _state = await response . json ( ) ;
updateSecretDisplay ( ) ;
await checkOpenRouterAuth ( ) ;
}
} catch {
console . error ( 'Could not read secrets file' ) ;
}
}
2024-02-23 20:41:54 +01:00
/ * *
* Finds a secret value by key .
* @ param { string } key Secret key
* @ returns { Promise < string | undefined > } Secret value , or undefined if keys are not exposed
* /
2023-11-20 06:34:06 +01:00
export async function findSecret ( key ) {
try {
const response = await fetch ( '/api/secrets/find' , {
method : 'POST' ,
headers : getRequestHeaders ( ) ,
body : JSON . stringify ( { key } ) ,
} ) ;
if ( response . ok ) {
const data = await response . json ( ) ;
2023-12-02 20:11:06 +01:00
return data . value ;
2023-11-20 06:34:06 +01:00
}
} catch {
console . error ( 'Could not find secret value: ' , key ) ;
}
}
2023-07-20 19:32:15 +02:00
function authorizeOpenRouter ( ) {
const openRouterUrl = ` https://openrouter.ai/auth?callback_url= ${ encodeURIComponent ( location . origin ) } ` ;
location . href = openRouterUrl ;
}
async function checkOpenRouterAuth ( ) {
const params = new URLSearchParams ( location . search ) ;
if ( params . has ( 'code' ) ) {
const code = params . get ( 'code' ) ;
try {
2023-12-02 19:04:51 +01:00
const response = await fetch ( 'https://openrouter.ai/api/v1/auth/keys' , {
2023-07-20 19:32:15 +02:00
method : 'POST' ,
body : JSON . stringify ( { code } ) ,
} ) ;
if ( ! response . ok ) {
throw new Error ( 'OpenRouter exchange error' ) ;
}
const data = await response . json ( ) ;
if ( ! data || ! data . key ) {
throw new Error ( 'OpenRouter invalid response' ) ;
}
await writeSecret ( SECRET _KEYS . OPENROUTER , data . key ) ;
if ( secret _state [ SECRET _KEYS . OPENROUTER ] ) {
toastr . success ( 'OpenRouter token saved' ) ;
// Remove the code from the URL
const currentUrl = window . location . href ;
2023-12-02 19:04:51 +01:00
const urlWithoutSearchParams = currentUrl . split ( '?' ) [ 0 ] ;
window . history . pushState ( { } , '' , urlWithoutSearchParams ) ;
2023-07-20 19:32:15 +02:00
} else {
throw new Error ( 'OpenRouter token not saved' ) ;
}
} catch ( err ) {
toastr . error ( 'Could not verify OpenRouter token. Please try again.' ) ;
return ;
}
}
}
jQuery ( async ( ) => {
$ ( '#viewSecrets' ) . on ( 'click' , viewSecrets ) ;
$ ( document ) . on ( 'click' , '.clear-api-key' , clearSecret ) ;
$ ( document ) . on ( 'input' , Object . values ( INPUT _MAP ) . join ( ',' ) , function ( ) {
const id = $ ( this ) . attr ( 'id' ) ;
const value = $ ( this ) . val ( ) ;
const warningElement = $ ( ` [data-for=" ${ id } "] ` ) ;
warningElement . toggle ( value . length > 0 ) ;
} ) ;
2024-02-25 21:47:07 +01:00
$ ( '.openrouter_authorize' ) . on ( 'click' , authorizeOpenRouter ) ;
2023-07-20 19:32:15 +02:00
} ) ;