Refactor API key management in extensions
| @@ -768,7 +768,7 @@ jQuery(async () => { | ||
| 768 | 768 | return; |
| 769 | 769 | } |
| 770 | 770 | |
| 771 | 771 | await writeSecret(extension_settings.translate.provider, String(key)); |
| 772 | 772 | toastr.success('API Key saved'); |
| 773 | 773 | $('#translate_key_button').addClass('success'); |
| 774 | 774 | }); |
| @@ -802,7 +802,7 @@ jQuery(async () => { | ||
| 802 | 802 | return; |
| 803 | 803 | } |
| 804 | 804 | |
| 805 | 805 | await writeSecret(secretKey, String(url)); |
| 806 | 806 | |
| 807 | 807 | toastr.success('API URL saved'); |
| 808 | 808 | $('#translate_url_button').addClass('success'); |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | import { event_types, eventSource, getRequestHeaders } from '../../../script.js'; |
| 2 | 2 | import { POPUP_RESULT, POPUP_TYPESECRET_KEYS, callGenericPopupsecret_state } from '../../popupsecrets.js'; |
| 3 | -import { SECRET_KEYS, findSecret, secret_state, writeSecret } from '../../secrets.js'; | |
| 4 | 3 | import { getPreviewString, saveTtsProviderSettings } from './index.js'; |
| 5 | 4 | export { AzureTtsProvider }; |
| 6 | 5 | |
| @@ -26,7 +25,7 @@ class AzureTtsProvider { | ||
| 26 | 25 | <h4 for="azure_tts_key" class="flex1 margin0"> |
| 27 | 26 | <a href="https://portal.azure.com/" target="_blank">Azure TTS Key</a> |
| 28 | 27 | </h4> |
| 29 | 28 | <div id="azure_tts_key" class="menu_button menu_button_icon manage-api-keys" data-key="api_key_azure_tts"> |
| 30 | 29 | <i class="fa-solid fa-key"></i> |
| 31 | 30 | <span>Click to set</span> |
| 32 | 31 | </div> |
| @@ -39,6 +38,20 @@ class AzureTtsProvider { | ||
| 39 | 38 | return html; |
| 40 | 39 | } |
| 41 | 40 | |
| 41 | + constructor() { | |
| 42 | + this.handler = async function (/** @type {string} */ key) { | |
| 43 | + if (key !== SECRET_KEYS.AZURE_TTS) return; | |
| 44 | + $('#azure_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.AZURE_TTS]); | |
| 45 | + await this.onRefreshClick(); | |
| 46 | + }.bind(this); | |
| 47 | + } | |
| 48 | + | |
| 49 | + dispose() { | |
| 50 | + [event_types.SECRET_WRITTEN, event_types.SECRET_DELETED, event_types.SECRET_ROTATED].forEach(event => { | |
| 51 | + eventSource.removeListener(event, this.handler); | |
| 52 | + }); | |
| 53 | + } | |
| 54 | + | |
| 42 | 55 | onSettingsChange() { |
| 43 | 56 | // Update dynamically |
| 44 | 57 | this.settings.region = String($('#azure_tts_region').val()); |
| @@ -65,34 +78,9 @@ class AzureTtsProvider { | ||
| 65 | 78 | } |
| 66 | 79 | |
| 67 | 80 | $('#azure_tts_region').val(this.settings.region).on('input', () => this.onSettingsChange()); |
| 68 | 81 | $('#azure_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.AZURE_TTS]); |
| 69 | - $('#azure_tts_key').on('click', async () => { | |
| 82 | + [event_types.SECRET_WRITTEN, event_types.SECRET_DELETED, event_types.SECRET_ROTATED].forEach(event => { | |
| 70 | - const popupText = 'Azure TTS API Key'; | |
| 83 | + eventSource.on(event, this.handler); | |
| 71 | - const savedKey = secret_state[SECRET_KEYS.AZURE_TTS] ? await findSecret(SECRET_KEYS.AZURE_TTS) : ''; | |
| 72 | - | |
| 73 | - const key = await callGenericPopup(popupText, POPUP_TYPE.INPUT, savedKey, { | |
| 74 | - customButtons: [{ | |
| 75 | - text: 'Remove Key', | |
| 76 | - appendAtEnd: true, | |
| 77 | - result: POPUP_RESULT.NEGATIVE, | |
| 78 | - action: async () => { | |
| 79 | - await writeSecret(SECRET_KEYS.AZURE_TTS, ''); | |
| 80 | - $('#azure_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.AZURE_TTS]); | |
| 81 | - toastr.success('API Key removed'); | |
| 82 | - await this.onRefreshClick(); | |
| 83 | - }, | |
| 84 | - }], | |
| 85 | - }); | |
| 86 | - | |
| 87 | - if (!key) { | |
| 88 | - return; | |
| 89 | - } | |
| 90 | - | |
| 91 | - await writeSecret(SECRET_KEYS.AZURE_TTS, String(key)); | |
| 92 | - | |
| 93 | - toastr.success('API Key saved'); | |
| 94 | - $('#azure_tts_key').addClass('success'); | |
| 95 | - await this.onRefreshClick(); | |
| 96 | 84 | }); |
| 97 | 85 | |
| 98 | 86 | try { |
| @@ -1,6 +1,5 @@ | ||
| 1 | 1 | import { event_types, eventSource, getRequestHeaders } from '../../../script.js'; |
| 2 | 2 | import { callGenericPopup, POPUP_RESULTSECRET_KEYS, POPUP_TYPEsecret_state } from '../../popupsecrets.js'; |
| 3 | -import { findSecret, SECRET_KEYS, secret_state, writeSecret } from '../../secrets.js'; | |
| 4 | 3 | import { getPreviewString, saveTtsProviderSettings } from './index.js'; |
| 5 | 4 | |
| 6 | 5 | export { OpenAICompatibleTtsProvider }; |
| @@ -27,7 +26,7 @@ class OpenAICompatibleTtsProvider { | ||
| 27 | 26 | <div class="flex1"> |
| 28 | 27 | <input id="openai_compatible_tts_endpoint" type="text" class="text_pole" maxlength="500" value="${this.defaultSettings.provider_endpoint}"/> |
| 29 | 28 | </div> |
| 30 | 29 | <div id="openai_compatible_tts_key" class="menu_button menu_button_icon manage-api-keys" data-key="api_key_custom_openai_tts"> |
| 31 | 30 | <i class="fa-solid fa-key"></i> |
| 32 | 31 | <span>API Key</span> |
| 33 | 32 | </div> |
| @@ -41,6 +40,20 @@ class OpenAICompatibleTtsProvider { | ||
| 41 | 40 | return html; |
| 42 | 41 | } |
| 43 | 42 | |
| 43 | + constructor() { | |
| 44 | + this.handler = async function (/** @type {string} */ key) { | |
| 45 | + if (key !== SECRET_KEYS.CUSTOM_OPENAI_TTS) return; | |
| 46 | + $('#openai_compatible_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.CUSTOM_OPENAI_TTS]); | |
| 47 | + await this.onRefreshClick(); | |
| 48 | + }.bind(this); | |
| 49 | + } | |
| 50 | + | |
| 51 | + dispose() { | |
| 52 | + [event_types.SECRET_WRITTEN, event_types.SECRET_DELETED, event_types.SECRET_ROTATED].forEach(event => { | |
| 53 | + eventSource.removeListener(event, this.handler); | |
| 54 | + }); | |
| 55 | + } | |
| 56 | + | |
| 44 | 57 | async loadSettings(settings) { |
| 45 | 58 | // Populate Provider UI given input settings |
| 46 | 59 | if (Object.keys(settings).length == 0) { |
| @@ -74,34 +87,9 @@ class OpenAICompatibleTtsProvider { | ||
| 74 | 87 | |
| 75 | 88 | $('#openai_compatible_tts_speed_output').text(this.settings.speed); |
| 76 | 89 | |
| 77 | 90 | $('#openai_compatible_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.CUSTOM_OPENAI_TTS]); |
| 78 | - $('#openai_compatible_tts_key').on('click', async () => { | |
| 91 | + [event_types.SECRET_WRITTEN, event_types.SECRET_DELETED, event_types.SECRET_ROTATED].forEach(event => { | |
| 79 | - const popupText = 'OpenAI-compatible TTS API Key'; | |
| 92 | + eventSource.on(event, this.handler); | |
| 80 | - const savedKey = secret_state[SECRET_KEYS.CUSTOM_OPENAI_TTS] ? await findSecret(SECRET_KEYS.CUSTOM_OPENAI_TTS) : ''; | |
| 81 | - | |
| 82 | - const key = await callGenericPopup(popupText, POPUP_TYPE.INPUT, savedKey, { | |
| 83 | - customButtons: [{ | |
| 84 | - text: 'Remove Key', | |
| 85 | - appendAtEnd: true, | |
| 86 | - result: POPUP_RESULT.NEGATIVE, | |
| 87 | - action: async () => { | |
| 88 | - await writeSecret(SECRET_KEYS.CUSTOM_OPENAI_TTS, ''); | |
| 89 | - $('#openai_compatible_tts_key').toggleClass('success', !!secret_state[SECRET_KEYS.CUSTOM_OPENAI_TTS]); | |
| 90 | - toastr.success('API Key removed'); | |
| 91 | - await this.onRefreshClick(); | |
| 92 | - }, | |
| 93 | - }], | |
| 94 | - }); | |
| 95 | - | |
| 96 | - if (!key) { | |
| 97 | - return; | |
| 98 | - } | |
| 99 | - | |
| 100 | - await writeSecret(SECRET_KEYS.CUSTOM_OPENAI_TTS, String(key)); | |
| 101 | - | |
| 102 | - toastr.success('API Key saved'); | |
| 103 | - $('#openai_compatible_tts_key').toggleClass('success', secret_state[SECRET_KEYS.CUSTOM_OPENAI_TTS]); | |
| 104 | - await this.onRefreshClick(); | |
| 105 | 93 | }); |
| 106 | 94 | |
| 107 | 95 | await this.checkReady(); |
| @@ -22,7 +22,7 @@ import { | ||
| 22 | 22 | openThirdPartyExtensionMenu, |
| 23 | 23 | } from '../../extensions.js'; |
| 24 | 24 | import { collapseNewlines, registerDebugFunction } from '../../power-user.js'; |
| 25 | 25 | import { SECRET_KEYS, secret_state, writeSecret } from '../../secrets.js'; |
| 26 | 26 | import { getDataBankAttachments, getDataBankAttachmentsForSource, getFileAttachment } from '../../chats.js'; |
| 27 | 27 | import { debounce, getStringHash as calculateHash, waitUntilCondition, onlyUnique, splitRecursive, trimToStartSentence, trimToEndSentence, escapeHtml } from '../../utils.js'; |
| 28 | 28 | import { debounce_timeout } from '../../constants.js'; |
| @@ -33,7 +33,6 @@ import { SlashCommand } from '../../slash-commands/SlashCommand.js'; | ||
| 33 | 33 | import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js'; |
| 34 | 34 | import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js'; |
| 35 | 35 | import { slashCommandReturnHelper } from '../../slash-commands/SlashCommandReturnHelper.js'; |
| 36 | -import { callGenericPopup, POPUP_RESULT, POPUP_TYPE } from '../../popup.js'; | |
| 37 | 36 | import { generateWebLlmChatPrompt, isWebLlmSupported } from '../shared.js'; |
| 38 | 37 | import { WebLlmVectorProvider } from './webllm.js'; |
| 39 | 38 | import { removeReasoningFromString } from '../../reasoning.js'; |
| @@ -1494,32 +1493,6 @@ jQuery(async () => { | ||
| 1494 | 1493 | Object.assign(extension_settings.vectors, settings); |
| 1495 | 1494 | saveSettingsDebounced(); |
| 1496 | 1495 | }); |
| 1497 | - $('#api_key_nomicai').on('click', async () => { | |
| 1498 | - const popupText = 'NomicAI API Key:'; | |
| 1499 | - const key = await callGenericPopup(popupText, POPUP_TYPE.INPUT, '', { | |
| 1500 | - customButtons: [{ | |
| 1501 | - text: 'Remove Key', | |
| 1502 | - appendAtEnd: true, | |
| 1503 | - result: POPUP_RESULT.NEGATIVE, | |
| 1504 | - action: async () => { | |
| 1505 | - await writeSecret(SECRET_KEYS.NOMICAI, ''); | |
| 1506 | - toastr.success('API Key removed'); | |
| 1507 | - $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); | |
| 1508 | - saveSettingsDebounced(); | |
| 1509 | - }, | |
| 1510 | - }], | |
| 1511 | - }); | |
| 1512 | - | |
| 1513 | - if (!key) { | |
| 1514 | - return; | |
| 1515 | - } | |
| 1516 | - | |
| 1517 | - await writeSecret(SECRET_KEYS.NOMICAI, String(key)); | |
| 1518 | - $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); | |
| 1519 | - | |
| 1520 | - toastr.success('API Key saved'); | |
| 1521 | - saveSettingsDebounced(); | |
| 1522 | - }); | |
| 1523 | 1496 | $('#vectors_togetherai_model').val(settings.togetherai_model).on('change', () => { |
| 1524 | 1497 | settings.togetherai_model = String($('#vectors_togetherai_model').val()); |
| 1525 | 1498 | Object.assign(extension_settings.vectors, settings); |
| @@ -1777,6 +1750,12 @@ jQuery(async () => { | ||
| 1777 | 1750 | }); |
| 1778 | 1751 | |
| 1779 | 1752 | $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); |
| 1753 | + [event_types.SECRET_WRITTEN, event_types.SECRET_DELETED, event_types.SECRET_ROTATED].forEach(event => { | |
| 1754 | + eventSource.on(event, (/** @type {string} */ key)=> { | |
| 1755 | + if (key !== SECRET_KEYS.NOMICAI) return; | |
| 1756 | + $('#api_key_nomicai').toggleClass('success', !!secret_state[SECRET_KEYS.NOMICAI]); | |
| 1757 | + }); | |
| 1758 | + }); | |
| 1780 | 1759 | |
| 1781 | 1760 | toggleSettings(); |
| 1782 | 1761 | eventSource.on(event_types.MESSAGE_DELETED, onChatEvent); |
| @@ -145,7 +145,7 @@ | ||
| 145 | 145 | <label for="api_key_nomicai" class="flex1"> |
| 146 | 146 | <span data-i18n="NomicAI API Key">NomicAI API Key</span> |
| 147 | 147 | </label> |
| 148 | 148 | <div id="api_key_nomicai" class="menu_button menu_button_icon manage-api-keys" data-key="api_key_nomicai"> |
| 149 | 149 | <i class="fa-solid fa-key"></i> |
| 150 | 150 | <span data-i18n="Click to set">Click to set</span> |
| 151 | 151 | </div> |