diff --git a/lib/ai/providers/vip98k.ts b/lib/ai/providers/vip98k.ts index 4e250175b..992b760e3 100644 --- a/lib/ai/providers/vip98k.ts +++ b/lib/ai/providers/vip98k.ts @@ -12,6 +12,7 @@ import { import { VIP98K_BASE_URL, normalizeVip98kBaseUrl } from "@/lib/ai/vip98k-models"; import { shouldResolveVip98kResultDelivery } from "@/lib/ai/vip98k-result-delivery"; import { + addVip98kReferenceRetryToken, getStorageObjectKeyFromPublicUrl, getVip98kStagedMediaRetryDelay, shouldStageVip98kReferenceUrl, @@ -809,13 +810,27 @@ async function submitTask(params: { const maxAttempts = stagedReferences.length > 0 ? 3 : 1; for (let attempt = 1; attempt <= maxAttempts; attempt += 1) { + const requestBody = + attempt === 1 || !Array.isArray(params.body.file_urls) + ? params.body + : { + ...params.body, + file_urls: params.body.file_urls.map((value) => + typeof value === "string" && isStagedReferenceUrl(value) + ? addVip98kReferenceRetryToken( + value, + `${Date.now()}-${attempt}`, + ) + : value, + ), + }; const response = await fetch(`${baseURL}${path}`, { method: String(params.method || "POST").toUpperCase(), headers: { Authorization: `Bearer ${params.apiKey}`, "Content-Type": params.contentType || "application/json", }, - body: JSON.stringify(params.body), + body: JSON.stringify(requestBody), signal: AbortSignal.timeout(120_000), }); const payload = await parseJsonResponse(response); diff --git a/lib/ai/vip98k-reference-staging.ts b/lib/ai/vip98k-reference-staging.ts index 1c49e111e..ab96b3aaa 100644 --- a/lib/ai/vip98k-reference-staging.ts +++ b/lib/ai/vip98k-reference-staging.ts @@ -69,3 +69,10 @@ export function getVip98kStagedMediaRetryDelay(params: { } return params.attempt * 20_000; } + +export function addVip98kReferenceRetryToken(mediaUrl: string, token: string) { + const parsed = parseUrl(mediaUrl); + if (!parsed) return mediaUrl; + parsed.searchParams.set("sg_media_retry", token); + return parsed.toString(); +} diff --git a/tests/routes/vip98k-reference-routing.test.ts b/tests/routes/vip98k-reference-routing.test.ts index 3776e08fb..7269b1df8 100644 --- a/tests/routes/vip98k-reference-routing.test.ts +++ b/tests/routes/vip98k-reference-routing.test.ts @@ -10,6 +10,7 @@ import { isVip98kImageModelVisible, } from "@/lib/ai/vip98k-models"; import { + addVip98kReferenceRetryToken, getStorageObjectKeyFromPublicUrl, getVip98kStagedMediaRetryDelay, shouldStageVip98kReferenceUrl, @@ -77,6 +78,14 @@ test.describe("VIP98K reference-image routing", () => { stagedReferenceCount: 2, }), ).toBeNull(); + expect( + addVip98kReferenceRetryToken( + "https://cdn.example/reference.jpg?existing=1", + "retry-2", + ), + ).toBe( + "https://cdn.example/reference.jpg?existing=1&sg_media_retry=retry-2", + ); }); test("shows the newly published Nano Banana Pro image editor", () => {