fix: poll grsai image tasks and return originals
This commit is contained in:
parent
801d2c4644
commit
010d7d1be5
@ -664,6 +664,30 @@ async function sendGrsaiGptImageRequest(params: {
|
||||
responseKeys: isRecord(data) ? Object.keys(data).slice(0, 12) : [],
|
||||
});
|
||||
|
||||
if (!hasGrsaiImages(data)) {
|
||||
const status = getGrsaiStatus(data);
|
||||
if (status === "failed" || status === "error") {
|
||||
throw new Error(`图片生成失败: ${getGrsaiErrorMessage(data)}`);
|
||||
}
|
||||
|
||||
const taskId = getGrsaiTaskId(data);
|
||||
if (taskId) {
|
||||
logger.info(`${apiLogPrefix} Native response has no images, polling task result`, {
|
||||
taskId,
|
||||
progress: getGrsaiProgress(data),
|
||||
status: status || null,
|
||||
});
|
||||
return pollGrsaiDrawResult({
|
||||
baseURL,
|
||||
apiKey,
|
||||
taskId,
|
||||
timeoutMs: timeout,
|
||||
apiLogPrefix,
|
||||
timeoutLabel: "Grsai GPT Image",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
clearTimeout(timeoutId);
|
||||
@ -827,6 +851,20 @@ async function pollGrsaiNanoBananaResult(params: {
|
||||
taskId: string;
|
||||
timeoutMs: number;
|
||||
apiLogPrefix: string;
|
||||
}): Promise<any> {
|
||||
return pollGrsaiDrawResult({
|
||||
...params,
|
||||
timeoutLabel: "GRSAI Nano Banana",
|
||||
});
|
||||
}
|
||||
|
||||
async function pollGrsaiDrawResult(params: {
|
||||
baseURL: string;
|
||||
apiKey: string;
|
||||
taskId: string;
|
||||
timeoutMs: number;
|
||||
apiLogPrefix: string;
|
||||
timeoutLabel: string;
|
||||
}): Promise<any> {
|
||||
const resultUrl = `${params.baseURL.replace(/\/+$/, "")}/v1/draw/result`;
|
||||
const deadline = Date.now() + params.timeoutMs;
|
||||
@ -882,7 +920,7 @@ async function pollGrsaiNanoBananaResult(params: {
|
||||
lastPayload: JSON.stringify(lastPayload || {}).substring(0, 500),
|
||||
});
|
||||
throw new Error(
|
||||
`GRSAI Nano Banana 异步任务超时(${Math.round(params.timeoutMs / 1000)}秒),请稍后重试或切换备用模型`
|
||||
`${params.timeoutLabel} 异步任务超时(${Math.round(params.timeoutMs / 1000)}秒),请稍后重试或切换备用模型`
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ export class ExternalImageApiGenerationError extends Error {
|
||||
|
||||
type ExternalImageApiGeneratedImage = {
|
||||
id: number;
|
||||
url: string;
|
||||
originalUrl: string;
|
||||
thumbnailUrl: string;
|
||||
imageSize: string;
|
||||
@ -484,6 +485,18 @@ function filterCompatibleCandidates(
|
||||
return acceptedCandidates;
|
||||
}
|
||||
|
||||
function parseGeneratedImageMarkdownMeta(alt: string) {
|
||||
const metaMatch = alt.match(/thumb\|\|\|([^|]+)\|\|\|(.+)$/i);
|
||||
if (!metaMatch) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
originalUrl: normalizeText(metaMatch[1]),
|
||||
imageSize: normalizeText(metaMatch[2]),
|
||||
};
|
||||
}
|
||||
|
||||
export async function ensureHostedImageMarkdown(
|
||||
markdown: string,
|
||||
imageSize = "2K",
|
||||
@ -510,13 +523,21 @@ export async function ensureHostedImageMarkdown(
|
||||
|
||||
for (const match of matches) {
|
||||
const raw = match[0];
|
||||
const sourceUrl = match[2] || "";
|
||||
const alt = match[1] || "";
|
||||
const thumbnailSourceUrl = normalizeText(match[2]);
|
||||
const metadata = parseGeneratedImageMarkdownMeta(alt);
|
||||
const originalSourceUrl = metadata?.originalUrl || thumbnailSourceUrl;
|
||||
const resolvedImageSize = metadata?.imageSize || imageSize;
|
||||
const start = match.index ?? -1;
|
||||
if (start < 0) continue;
|
||||
|
||||
rebuilt += markdown.slice(cursor, start);
|
||||
const hostedUrl = await ensureHostedImageUrl(sourceUrl);
|
||||
rebuilt += ``;
|
||||
const hostedOriginalUrl = await ensureHostedImageUrl(originalSourceUrl);
|
||||
const hostedThumbnailUrl =
|
||||
thumbnailSourceUrl && thumbnailSourceUrl !== originalSourceUrl
|
||||
? await ensureHostedImageUrl(thumbnailSourceUrl)
|
||||
: hostedOriginalUrl;
|
||||
rebuilt += ``;
|
||||
cursor = start + raw.length;
|
||||
}
|
||||
|
||||
@ -533,13 +554,14 @@ export function extractGeneratedImagesFromMarkdown(markdown: string) {
|
||||
const thumbnailUrl = match[2] || "";
|
||||
let originalUrl = thumbnailUrl;
|
||||
let imageSize = "2K";
|
||||
const metaMatch = alt.match(/thumb\|\|\|([^|]+)\|\|\|(.+)$/i);
|
||||
if (metaMatch) {
|
||||
originalUrl = normalizeText(metaMatch[1]) || thumbnailUrl;
|
||||
imageSize = normalizeText(metaMatch[2]) || imageSize;
|
||||
const metadata = parseGeneratedImageMarkdownMeta(alt);
|
||||
if (metadata) {
|
||||
originalUrl = metadata.originalUrl || thumbnailUrl;
|
||||
imageSize = metadata.imageSize || imageSize;
|
||||
}
|
||||
return {
|
||||
id: index + 1,
|
||||
url: originalUrl,
|
||||
originalUrl,
|
||||
thumbnailUrl,
|
||||
imageSize,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user