From cbca37dd7743bcecc9c7dfdbcd7d40156f8983f5 Mon Sep 17 00:00:00 2001 From: reanon <85157-reanon@users.noreply.gitgud.io> Date: Sat, 26 Apr 2025 01:26:50 -0800 Subject: [PATCH] last test for image verif --- src/shared/key-management/openai/checker.ts | 78 ++++++++++++--------- 1 file changed, 46 insertions(+), 32 deletions(-) diff --git a/src/shared/key-management/openai/checker.ts b/src/shared/key-management/openai/checker.ts index 09a0ca2..93d6c5e 100644 --- a/src/shared/key-management/openai/checker.ts +++ b/src/shared/key-management/openai/checker.ts @@ -336,6 +336,9 @@ export class OpenAIKeyChecker extends KeyCheckerBase { /** * 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 { this.log.info({ key: key.hash }, "Testing gpt-image-1 access"); @@ -356,37 +359,37 @@ export class OpenAIKeyChecker extends KeyCheckerBase { { 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 { // 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; }