Handle long running custom image jobs

This commit is contained in:
Codex
2026-05-09 06:21:38 +00:00
parent c8f0c37cd1
commit 24eab34305
5 changed files with 91 additions and 37 deletions

View File

@@ -22,7 +22,7 @@ interface CustomApiConfig {
systemApiId?: string;
}
const GENERATION_TIMEOUT = 300_000;
const GENERATION_TIMEOUT = Number(process.env.IMAGE_GENERATION_TIMEOUT_MS || 900_000);
const GENERATION_TIMEOUT_SECONDS = GENERATION_TIMEOUT / 1000;
const MAX_UPSTREAM_REFERENCE_IMAGE_BYTES = Number(process.env.MAX_UPSTREAM_REFERENCE_IMAGE_BYTES || 700 * 1024);
@@ -202,7 +202,7 @@ async function fetchCustomImageGeneration(
endpoint,
{ method: 'POST', headers: buildCustomApiHeaders(apiKey), body: JSON.stringify(requestBody) },
GENERATION_TIMEOUT,
1,
0,
);
if (!response.ok) {
@@ -396,6 +396,30 @@ function objectKeysFromUnknown(value: unknown): string[] {
*/
function extractImagesFromGenerationsResponse(data: Record<string, unknown>): string[] {
const images: string[] = [];
const visit = (value: unknown, depth = 0) => {
if (depth > 6 || !value) return;
if (typeof value === 'string') {
if (value.startsWith('data:image/') || /^https?:\/\/[^\s"'<>]+/i.test(value)) images.push(value);
return;
}
if (Array.isArray(value)) {
for (const item of value) visit(item, depth + 1);
return;
}
if (typeof value !== 'object') return;
const object = value as Record<string, unknown>;
if (typeof object.b64_json === 'string') images.push(`data:image/png;base64,${object.b64_json}`);
if (typeof object.url === 'string') visit(object.url, depth + 1);
if (typeof object.image_url === 'string') visit(object.image_url, depth + 1);
if (typeof object.image === 'string') visit(object.image, depth + 1);
if (typeof object.output === 'string') visit(object.output, depth + 1);
if (typeof object.result === 'string') visit(object.result, depth + 1);
for (const key of ['data', 'images', 'image_urls', 'output', 'result', 'results', 'message', 'content']) {
if (key in object) visit(object[key], depth + 1);
}
};
if (Array.isArray(data.data)) {
for (const item of data.data as Array<Record<string, unknown>>) {
if (typeof item === 'string') { images.push(item); continue; }
@@ -409,6 +433,7 @@ function extractImagesFromGenerationsResponse(data: Record<string, unknown>): st
} else if (typeof data.image_url === 'string') {
images.push(data.image_url);
}
visit(data);
const streamEvents = data.__streamEvents;
if (Array.isArray(streamEvents)) {
@@ -418,7 +443,7 @@ function extractImagesFromGenerationsResponse(data: Record<string, unknown>): st
}
}
return images;
return Array.from(new Set(images));
}
/** Track which strategy produced a result */
@@ -454,7 +479,7 @@ async function tryImageStrategy(
body: JSON.stringify(body),
},
GENERATION_TIMEOUT,
1,
0,
);
if (response.ok) {
@@ -557,7 +582,7 @@ async function tryEditsWithFormData(
body: bodyBuffer,
},
GENERATION_TIMEOUT,
1,
0,
);
if (response.ok) {