last test for image verif
This commit is contained in:
@@ -336,6 +336,9 @@ export class OpenAIKeyChecker extends KeyCheckerBase<OpenAIKey> {
|
||||
/**
|
||||
* Tests whether the key has access to the gpt-image-1 model by making a small test request.
|
||||
* Returns true if the key has access, false otherwise.
|
||||
*
|
||||
* Ensures that the key can actually generate images by verifying the API response
|
||||
* contains the expected data structure for successful image generation.
|
||||
*/
|
||||
public async testGptImageAccess(key: OpenAIKey): Promise<boolean> {
|
||||
this.log.info({ key: key.hash }, "Testing gpt-image-1 access");
|
||||
@@ -356,37 +359,37 @@ export class OpenAIKeyChecker extends KeyCheckerBase<OpenAIKey> {
|
||||
{
|
||||
headers: OpenAIKeyChecker.getHeaders(key),
|
||||
validateStatus: (status) => status >= 200 && status < 500, // Accept any non-server error response
|
||||
timeout: 5000, // 5 second timeout
|
||||
signal: AbortSignal.timeout(5000)
|
||||
timeout: 200000, // 200 second timeout to allow for image generation
|
||||
signal: AbortSignal.timeout(200000)
|
||||
}
|
||||
);
|
||||
|
||||
// Status 200 means unquestionable success
|
||||
// Status 200 means success, but we need to verify the response actually contains image data
|
||||
if (response.status === 200) {
|
||||
this.log.info(
|
||||
{ key: key.hash, status: response.status },
|
||||
"Verified gpt-image-1 access: Successfully generated an image"
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check for validation errors that still indicate the model is available
|
||||
if (response.status === 400) {
|
||||
const data = response.data as any;
|
||||
if (data?.error?.type === "invalid_request_error" &&
|
||||
!data?.error?.message?.includes("model")) {
|
||||
// This is likely a parameter error, not a model access issue
|
||||
// Check if the response contains the expected data structure
|
||||
if (response.data &&
|
||||
response.data.data &&
|
||||
Array.isArray(response.data.data) &&
|
||||
response.data.data.length > 0 &&
|
||||
response.data.data[0].url) {
|
||||
this.log.info(
|
||||
{ key: key.hash, status: response.status, error: data?.error?.message },
|
||||
"Key has access to gpt-image-1 but encountered parameter validation issues"
|
||||
{ key: key.hash, status: response.status },
|
||||
"Verified gpt-image-1 access: Successfully generated an image"
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
this.log.warn(
|
||||
{ key: key.hash, status: response.status, data: response.data },
|
||||
"Response status is 200 but received unexpected response format. Image may not have been generated."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Got an unexpected error response
|
||||
// All other status codes indicate issues
|
||||
const data = response.data as any;
|
||||
this.log.warn(
|
||||
{ key: key.hash, status: response.status, data: response.data },
|
||||
{ key: key.hash, status: response.status, error: data?.error?.message || 'Unknown error' },
|
||||
"Unexpected response when testing gpt-image-1 access, assuming no access"
|
||||
);
|
||||
return false;
|
||||
@@ -396,30 +399,41 @@ export class OpenAIKeyChecker extends KeyCheckerBase<OpenAIKey> {
|
||||
// Check for forbidden/unauthorized responses
|
||||
const status = error.response.status;
|
||||
const data = error.response.data as any;
|
||||
const errorMessage = data?.error?.message || 'Unknown error';
|
||||
|
||||
// 403 with message about organization verification means the key doesn't have access
|
||||
if (status === 403 && data?.error?.message?.includes("Your organization must be verified")) {
|
||||
// Organization verification errors (403 forbidden)
|
||||
if (status === 403) {
|
||||
this.log.warn(
|
||||
{ key: key.hash, error: data.error.message },
|
||||
"Key does not have access to gpt-image-1: organization verification required"
|
||||
{ key: key.hash, error: errorMessage },
|
||||
"Key does not have access to gpt-image-1: received 403 Forbidden response"
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// If it's a rate limit error, consider it valid since the API is accepting the model name
|
||||
if (status === 429) {
|
||||
this.log.info(
|
||||
{ key: key.hash, status, error: data?.error?.message },
|
||||
"Key has access to gpt-image-1 but is rate limited"
|
||||
// Explicitly handle all status codes that indicate the key doesn't have access
|
||||
if (status === 401 || status === 404 || status === 400) {
|
||||
this.log.warn(
|
||||
{ key: key.hash, status, error: errorMessage },
|
||||
`Key does not have access to gpt-image-1: received ${status} response`
|
||||
);
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Rate limit errors - we no longer assume these mean the key has access
|
||||
// since the rate limit could be happening before model validation
|
||||
if (status === 429) {
|
||||
this.log.warn(
|
||||
{ key: key.hash, status, error: errorMessage },
|
||||
"Cannot verify gpt-image-1 access: key is rate limited. Assuming no access for safety."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// For other errors, assume no access
|
||||
// For all other errors, assume no access
|
||||
this.log.error(
|
||||
{ key: key.hash, error: error.message },
|
||||
"Unexpected error testing gpt-image-1 access"
|
||||
"Unexpected error testing gpt-image-1 access. Assuming no access for safety."
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user