Report OpenAI quota errors in admin
This commit is contained in:
@@ -479,19 +479,24 @@ async function adminAiTest(res) {
|
||||
const apiKey = settings.openaiApiKey;
|
||||
if (!apiKey) return json(res, 400, { ok: false, error: "missing_openai_api_key" });
|
||||
try {
|
||||
const response = await fetch("https://api.openai.com/v1/models", {
|
||||
const modelsResponse = await fetch("https://api.openai.com/v1/models", {
|
||||
headers: { "Authorization": `Bearer ${apiKey}` }
|
||||
});
|
||||
if (!response.ok) return json(res, 400, { ok: false, error: `openai_http_${response.status}` });
|
||||
const data = await response.json();
|
||||
if (!modelsResponse.ok) {
|
||||
const openAiError = await openAiErrorFromResponse(modelsResponse);
|
||||
return json(res, 400, { ok: false, error: openAiError.code, message: openAiError.message });
|
||||
}
|
||||
const data = await modelsResponse.json();
|
||||
await translateText("Test", settings.operatorLanguage || "cs", settings.model, apiKey);
|
||||
return json(res, 200, {
|
||||
ok: true,
|
||||
key: maskApiKey(apiKey),
|
||||
model: settings.model,
|
||||
modelCount: Array.isArray(data.data) ? data.data.length : 0
|
||||
});
|
||||
} catch (error) {
|
||||
console.error("openai_test_failed", error.message);
|
||||
return json(res, 502, { ok: false, error: "openai_test_failed" });
|
||||
return json(res, 400, { ok: false, error: classifyOpenAiError(error.message), message: error.message });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -807,7 +812,7 @@ async function translateStoredMessage(conversationId, messageId, senderType, bod
|
||||
markMessageTranslation(messageId, sourceLanguage, translatedText, translatedLanguage, "translated", null);
|
||||
} catch (error) {
|
||||
console.error("translation_failed", error.message);
|
||||
markMessageTranslation(messageId, null, null, targetLanguage, "failed", error.message);
|
||||
markMessageTranslation(messageId, null, null, targetLanguage, classifyOpenAiError(error.message), error.message);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -848,13 +853,38 @@ async function translateText(text, targetLanguage, model, apiKey) {
|
||||
})
|
||||
});
|
||||
if (!response.ok) {
|
||||
const errorBody = await response.text().catch(() => "");
|
||||
throw new Error(`OpenAI HTTP ${response.status}${errorBody ? `: ${errorBody.slice(0, 300)}` : ""}`);
|
||||
const openAiError = await openAiErrorFromResponse(response);
|
||||
throw new Error(openAiError.message);
|
||||
}
|
||||
const data = await response.json();
|
||||
return parseTranslationJson(outputTextFromResponse(data));
|
||||
}
|
||||
|
||||
async function openAiErrorFromResponse(response) {
|
||||
const errorBody = await response.text().catch(() => "");
|
||||
let message = errorBody;
|
||||
let code = `openai_http_${response.status}`;
|
||||
try {
|
||||
const parsed = JSON.parse(errorBody);
|
||||
message = parsed?.error?.message || message;
|
||||
code = parsed?.error?.code || parsed?.error?.type || code;
|
||||
} catch {}
|
||||
const classifiedCode = classifyOpenAiError(`${code} ${message}`);
|
||||
return {
|
||||
code: classifiedCode,
|
||||
message: `OpenAI HTTP ${response.status}: ${message || response.statusText || classifiedCode}`
|
||||
};
|
||||
}
|
||||
|
||||
function classifyOpenAiError(value) {
|
||||
const text = String(value || "").toLowerCase();
|
||||
if (text.includes("insufficient_quota") || text.includes("exceeded your current quota") || text.includes("billing")) return "quota_exceeded";
|
||||
if (text.includes("invalid_api_key") || text.includes("incorrect api key") || text.includes("unauthorized") || text.includes("401")) return "invalid_key";
|
||||
if (text.includes("rate_limit") || text.includes("too many requests")) return "rate_limited";
|
||||
if (text.includes("model") && (text.includes("not found") || text.includes("does not exist"))) return "bad_model";
|
||||
return "failed";
|
||||
}
|
||||
|
||||
function parseTranslationJson(value) {
|
||||
try {
|
||||
const text = String(value || "").trim().replace(/^```(?:json)?/i, "").replace(/```$/, "").trim();
|
||||
|
||||
Reference in New Issue
Block a user