From 48f062897bd41b832f1cf7925177d7519386ef4b Mon Sep 17 00:00:00 2001 From: Your Name Date: Sat, 7 Feb 2026 20:38:39 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DRUXA=E7=BB=93=E6=9E=9C?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E5=AF=BC=E8=87=B4=E4=BB=BB=E5=8A=A1=E8=B6=85?= =?UTF-8?q?=E6=97=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/ai/providers/ruxa-image.ts | 72 +++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 27 deletions(-) diff --git a/lib/ai/providers/ruxa-image.ts b/lib/ai/providers/ruxa-image.ts index d448b10..0214eda 100644 --- a/lib/ai/providers/ruxa-image.ts +++ b/lib/ai/providers/ruxa-image.ts @@ -154,6 +154,21 @@ function collectImageUrls(payload: any): string[] { if (typeof value === "string") { if (isLikelyImageUrl(value) || (isImageLikeKey(parentKey) && /^https?:\/\//i.test(value))) { urls.add(value); + return; + } + + const trimmed = value.trim(); + if ( + trimmed.length > 1 && + trimmed.length < 200000 && + (trimmed.startsWith("{") || trimmed.startsWith("[")) + ) { + try { + const parsed = JSON.parse(trimmed); + walk(parsed, parentKey); + } catch { + // ignore non-JSON strings + } } return; } @@ -244,41 +259,44 @@ async function waitForTaskResult(baseURL: string, apiKey: string, taskId: string (id: string) => joinApiPath(baseURL, `/api/v1/tasks/${id}`), (id: string) => `${joinApiPath(baseURL, "/api/v1/tasks/query")}?taskId=${encodeURIComponent(id)}`, ]; + let endpointIndex = 0; for (let attempt = 1; attempt <= POLL_MAX_ATTEMPTS; attempt++) { - for (const endpointBuilder of endpointCandidates) { - try { - const endpoint = endpointBuilder(taskId); - const response = await fetch(endpoint, { - headers: { - Authorization: `Bearer ${apiKey}`, - "Content-Type": "application/json", - }, - }); + try { + const endpoint = endpointCandidates[endpointIndex]!(taskId); + const response = await fetch(endpoint, { + headers: { + Authorization: `Bearer ${apiKey}`, + "Content-Type": "application/json", + }, + }); - if (!response.ok) { - continue; + if (!response.ok) { + if (response.status === 404 && endpointIndex < endpointCandidates.length - 1) { + endpointIndex++; } + await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS)); + continue; + } - const payload = await response.json(); - const imageUrls = filterSourceImages(collectImageUrls(payload), sourceUrls); - const status = extractStatus(payload); + const payload = await response.json(); + const imageUrls = filterSourceImages(collectImageUrls(payload), sourceUrls); + const status = extractStatus(payload); - if (imageUrls.length > 0) { - return imageUrls; - } + if (imageUrls.length > 0) { + return imageUrls; + } - if (status && ["failed", "error", "cancelled", "canceled"].includes(status)) { - throw new Error(extractErrorMessage(payload)); - } + if (status && ["failed", "error", "cancelled", "canceled"].includes(status)) { + throw new Error(extractErrorMessage(payload)); + } - if (status && ["success", "succeeded", "completed", "done", "finished"].includes(status)) { - throw new Error("任务已完成但未返回图片地址"); - } - } catch (error) { - if (error instanceof Error && error.message !== "任务已完成但未返回图片地址") { - throw error; - } + if (status && ["success", "succeeded", "completed", "done", "finished"].includes(status)) { + throw new Error("任务已完成但未返回图片地址"); + } + } catch (error) { + if (error instanceof Error && error.message !== "任务已完成但未返回图片地址") { + throw error; } }