Fix make /profile await the for an actual successful API connection (#4589)

* fix: add connection status check after profile switch in connection manager

Fixes #4262

* feat: add timeout parameter to connection manager await functionality & catch timout error

* Add rejectOnTimeout option to waitUntilCondition

---------

Co-authored-by: Cohee <18619528+Cohee1207@users.noreply.github.com>
This commit is contained in:
Wolfsblvt
2025-10-03 19:43:35 +02:00
committed by GitHub
parent 654ddb1608
commit df2dee8482
2 changed files with 23 additions and 4 deletions
@@ -1,6 +1,6 @@
import { DOMPurify, Fuse } from '../../../lib.js';
import { event_types, eventSource, main_api, saveSettingsDebounced } from '../../../script.js';
import { event_types, eventSource, main_api, online_status, saveSettingsDebounced } from '../../../script.js';
import { extension_settings, renderExtensionTemplateAsync } from '../../extensions.js';
import { callGenericPopup, Popup, POPUP_RESULT, POPUP_TYPE } from '../../popup.js';
import { SlashCommand } from '../../slash-commands/SlashCommand.js';
@@ -11,7 +11,7 @@ import { SlashCommandDebugController } from '../../slash-commands/SlashCommandDe
import { enumTypes, SlashCommandEnumValue } from '../../slash-commands/SlashCommandEnumValue.js';
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
import { SlashCommandScope } from '../../slash-commands/SlashCommandScope.js';
import { collapseSpaces, getUniqueName, isFalseBoolean, uuidv4 } from '../../utils.js';
import { collapseSpaces, getUniqueName, isFalseBoolean, uuidv4, waitUntilCondition } from '../../utils.js';
import { t } from '../../i18n.js';
import { getSecretLabelById } from '../../secrets.js';
@@ -684,6 +684,13 @@ async function renderDetailsContent(detailsContent) {
defaultValue: 'true',
enumList: commonEnumProviders.boolean('trueFalse')(),
}),
SlashCommandNamedArgument.fromProps({
name: 'timeout',
description: 'Maximum time to wait for the API connection to be established, in milliseconds. Set to 0 to disable. Only applies when await=true.',
isRequired: false,
typeList: [ARGUMENT_TYPE.NUMBER],
defaultValue: '2000',
}),
],
callback: async (args, value) => {
if (!value || typeof value !== 'string') {
@@ -715,6 +722,13 @@ async function renderDetailsContent(detailsContent) {
if (shouldAwait) {
await awaitPromise;
// We should also await the connection to be established
const parsedTimeout = parseInt(args?.timeout?.toString());
const timeout = !isNaN(parsedTimeout) ? Math.max(0, parsedTimeout) : 2000;
if (timeout > 0) {
await waitUntilCondition(() => online_status !== 'no_connection', timeout, 100, { rejectOnTimeout: false });
}
}
return profile.name;
+7 -2
View File
@@ -1637,13 +1637,18 @@ export function createThumbnail(dataUrl, maxWidth = null, maxHeight = null, type
* @param {{ (): boolean; }} condition The condition to wait for.
* @param {number} [timeout=1000] The timeout in milliseconds.
* @param {number} [interval=100] The interval in milliseconds.
* @param {object} [options] Options object
* @param {boolean} [options.rejectOnTimeout=true] Whether to reject the promise on timeout or resolve it.
* @returns {Promise<void>} A promise that resolves when the condition is true.
*/
export async function waitUntilCondition(condition, timeout = 1000, interval = 100) {
export async function waitUntilCondition(condition, timeout = 1000, interval = 100, options = {}) {
const { rejectOnTimeout = true } = options;
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
clearInterval(intervalId);
reject(new Error('Timed out waiting for condition to be true'));
const timeoutFn = rejectOnTimeout ? reject : resolve;
timeoutFn(new Error('Timed out waiting for condition to be true'));
}, timeout);
const intervalId = setInterval(() => {