Refactor CC API async route handlers (#4885) * Improve error handling in CC /status and /generate endpoints * Cancel pending status check on switching CC source

9046fe8d2de22b166e588839c8579c9b1da754c0

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

Signed
3 files changed, +35 -53Showing whitespace changes
public/script.js+1 -1
@@ -744,7 +744,7 @@ function initStandaloneMode() {
744744 }
745745}
746746
747747export function cancelStatusCheck(reason = 'Manually cancelled status check') {
748748 abortStatusCheck?.abort(new AbortReason(reason));
749749 abortStatusCheck = new AbortController();
750750 setOnlineStatus('no_connection');
public/scripts/openai.js+2 -0
@@ -7,6 +7,7 @@ import { Fuse, DOMPurify } from '../lib.js';
77
88import {
99 abortStatusCheck,
10+ cancelStatusCheck,
1011 characters,
1112 event_types,
1213 eventSource,
@@ -6349,6 +6350,7 @@ export function initOpenAI() {
63496350 });
63506351
63516352 $('#chat_completion_source').on('change', function () {
6353+ cancelStatusCheck('Chat Completion source changed');
63526354 model_list = [];
63536355 oai_settings.chat_completion_source = String($(this).find(':selected').val());
63546356 toggleChatCompletionForms();
src/endpoints/backends/chat-completions.js+32 -52
@@ -1560,6 +1560,7 @@ async function sendAzureOpenAIRequest(request, response) {
15601560export const router = express.Router();
15611561
15621562router.post('/status', async function (request, statusResponse) {
1563+ try {
15631564 if (!request.body) return statusResponse.sendStatus(400);
15641565
15651566 let apiUrl = '';
@@ -1763,7 +1764,6 @@ router.post('/status', async function (request, statusResponse) {
17631764 return statusResponse.status(400).send({ error: true });
17641765 }
17651766
1766- try {
17671767 const modelsUrl = new URL(urlJoin(apiUrl, '/models'));
17681768 Object.keys(queryParams).forEach(key => {
17691769 modelsUrl.searchParams.append(key, queryParams[key]);
@@ -1933,8 +1933,8 @@ router.post('/bias', async function (request, response) {
19331933 }
19341934});
19351935
1936-
1936+router.post('/generate', async function (request, response) {
1937-router.post('/generate', function (request, response) {
1937+ try {
19381938 if (!request.body) return response.status(400).send({ error: true });
19391939
19401940 const postProcessingType = request.body.custom_prompt_post_processing;
@@ -1951,18 +1951,18 @@ router.post('/generate', function (request, response) {
19511951 }
19521952
19531953 switch (request.body.chat_completion_source) {
19541954 case CHAT_COMPLETION_SOURCES.CLAUDE: return await sendClaudeRequest(request, response);
19551955 case CHAT_COMPLETION_SOURCES.AI21: return await sendAI21Request(request, response);
19561956 case CHAT_COMPLETION_SOURCES.MAKERSUITE: return await sendMakerSuiteRequest(request, response);
19571957 case CHAT_COMPLETION_SOURCES.VERTEXAI: return await sendMakerSuiteRequest(request, response);
19581958 case CHAT_COMPLETION_SOURCES.MISTRALAI: return await sendMistralAIRequest(request, response);
19591959 case CHAT_COMPLETION_SOURCES.COHERE: return await sendCohereRequest(request, response);
19601960 case CHAT_COMPLETION_SOURCES.DEEPSEEK: return await sendDeepSeekRequest(request, response);
19611961 case CHAT_COMPLETION_SOURCES.AIMLAPI: return await sendAimlapiRequest(request, response);
19621962 case CHAT_COMPLETION_SOURCES.XAI: return await sendXaiRequest(request, response);
19631963 case CHAT_COMPLETION_SOURCES.CHUTES: return await sendChutesRequest(request, response);
19641964 case CHAT_COMPLETION_SOURCES.ELECTRONHUB: return await sendElectronHubRequest(request, response);
19651965 case CHAT_COMPLETION_SOURCES.AZURE_OPENAI: return await sendAzureOpenAIRequest(request, response);
19661966 }
19671967
19681968 let apiUrl;
@@ -2300,32 +2300,33 @@ router.post('/generate', function (request, response) {
23002300
23012301 console.debug('Chat Completion request:', requestBody);
23022302
2303- makeRequest(config, response, request);
2304-
2305- /**
2306- * Makes a fetch request to the OpenAI API endpoint.
2307- * @param {import('node-fetch').RequestInit} config Fetch config
2308- * @param {express.Response} response Express response
2309- * @param {express.Request} request Express request
2310- */
2311- async function makeRequest(config, response, request) {
2312- try {
2313- controller.signal.throwIfAborted();
23142303 const fetchResponse = await fetch(endpointUrl, config);
23152304
23162305 if (request.body.stream) {
23172306 console.info('Streaming request in progress');
23182307 return forwardFetchResponse(fetchResponse, response);
2319- return;
23202308 }
23212309
23222310 if (fetchResponse.ok) {
23232311 /** @type {any} */
23242312 let const json = await fetchResponse.json();
2325- response.send(json);
23262313 console.debug('Chat Completion response:', json);
2314+ return response.send(json);
2315+ } else {
2316+ const responseText = await fetchResponse.text();
2317+ const errorData = tryParse(responseText);
2318+
2319+ const message = fetchResponse.statusText || 'Unknown error occurred';
2320+ const quota_error = fetchResponse.status === 429 && errorData?.error?.type === 'insufficient_quota';
2321+ console.error('Chat completion request error: ', message, responseText);
2322+
2323+ if (!response.headersSent) {
2324+ response.send({ error: { message }, quota_error: quota_error });
2325+ } else if (!response.writableEnded) {
2326+ response.write(responseText);
23272327 } else {
23282328 await handleErrorResponseresponse.end(fetchResponse);
2329+ }
23292330 }
23302331 } catch (error) {
23312332 console.error('Generation failed', error);
@@ -2339,27 +2340,6 @@ router.post('/generate', function (request, response) {
23392340 response.end();
23402341 }
23412342 }
2342- }
2343-
2344- /**
2345- * @param {import("node-fetch").Response} errorResponse
2346- */
2347- async function handleErrorResponse(errorResponse) {
2348- const responseText = await errorResponse.text();
2349- const errorData = tryParse(responseText);
2350-
2351- const message = errorResponse.statusText || 'Unknown error occurred';
2352- const quota_error = errorResponse.status === 429 && errorData?.error?.type === 'insufficient_quota';
2353- console.error('Chat completion request error: ', message, responseText);
2354-
2355- if (!response.headersSent) {
2356- response.send({ error: { message }, quota_error: quota_error });
2357- } else if (!response.writableEnded) {
2358- response.write(responseText);
2359- } else {
2360- response.end();
2361- }
2362- }
23632343});
23642344
23652345const multimodalModels = express.Router();