From 19bf03542c2b6407407e7a309c93df1cccc3f481 Mon Sep 17 00:00:00 2001 From: wauputr4 <103489788+wauputr4@users.noreply.github.com> Date: Thu, 23 Apr 2026 15:03:44 +0000 Subject: [PATCH] refactor(providers): robust KIE handlers with dynamic polling and improved types --- open-sse/handlers/imageGeneration.ts | 28 ++++++++++----- open-sse/handlers/musicGeneration.ts | 42 +++++++++++++--------- open-sse/handlers/videoGeneration.ts | 52 +++++++++++++++++++--------- 3 files changed, 81 insertions(+), 41 deletions(-) diff --git a/open-sse/handlers/imageGeneration.ts b/open-sse/handlers/imageGeneration.ts index b651ec44b4..070022ca55 100644 --- a/open-sse/handlers/imageGeneration.ts +++ b/open-sse/handlers/imageGeneration.ts @@ -347,10 +347,15 @@ async function handleKieImageGeneration({ }); } - const statusUrl = providerConfig.baseUrl.replace("/generate", "/record-info"); + const statusUrl = providerConfig.baseUrl + .replace(/\/generate$/, "/record-info") + .replace("/api/v1/gpt4o-image/generate", "/api/v1/gpt4o-image/record-info"); const deadline = Date.now() + timeoutMs; while (Date.now() < deadline) { - const recordRes = await fetch(`${statusUrl}?taskId=${encodeURIComponent(taskId)}`, { + const pollUrl = new URL(statusUrl); + pollUrl.searchParams.set("taskId", String(taskId)); + + const recordRes = await fetch(pollUrl.toString(), { method: "GET", headers: { Authorization: `Bearer ${token}`, @@ -374,13 +379,15 @@ async function handleKieImageGeneration({ recordData?.data?.status ?? recordData?.data?.successFlag ?? recordData?.msg ?? "PENDING" ).toUpperCase(); - if (state === "SUCCESS" || state === "1") { + if (state === "SUCCESS" || state === "1" || state === "FINISHED") { const urls = Array.isArray(recordData?.data?.response?.resultUrls) ? recordData.data.response.resultUrls - : []; + : Array.isArray(recordData?.data?.resultImageUrls) + ? recordData.data.resultImageUrls + : []; const images = urls - .filter((url) => typeof url === "string" && url.length > 0) - .map((url) => ({ url, revised_prompt: body.prompt })); + .filter((url: unknown) => typeof url === "string" && url.length > 0) + .map((url: unknown) => ({ url: url as string, revised_prompt: body.prompt })); return saveImageSuccessResult({ provider, model, @@ -391,16 +398,21 @@ async function handleKieImageGeneration({ }); } + // Expanded failure state detection if ( - state.includes("FAIL") || - state.includes("ERROR") || + state === "FAIL" || + state === "FAILED" || + state === "ERROR" || state === "2" || state === "3" || + state.includes("FAIL") || + state.includes("ERROR") || state === "CREATE_TASK_FAILED" || state === "GENERATE_FAILED" ) { const errorMessage = recordData?.data?.errorMessage || + recordData?.data?.failMsg || recordData?.msg || `KIE image task failed with status: ${state}`; return saveImageErrorResult({ diff --git a/open-sse/handlers/musicGeneration.ts b/open-sse/handlers/musicGeneration.ts index 4d610ccc1e..d05494b073 100644 --- a/open-sse/handlers/musicGeneration.ts +++ b/open-sse/handlers/musicGeneration.ts @@ -216,16 +216,18 @@ async function handleKieMusicGeneration({ } const deadline = Date.now() + timeoutMs; + const statusBaseUrl = `${baseUrl}/api/v1/generate/record-info`; + while (Date.now() < deadline) { - const recordRes = await fetch( - `${baseUrl}/api/v1/generate/record-info?taskId=${encodeURIComponent(taskId)}`, - { - method: "GET", - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); + const pollUrl = new URL(statusBaseUrl); + pollUrl.searchParams.set("taskId", String(taskId)); + + const recordRes = await fetch(pollUrl.toString(), { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + }, + }); if (!recordRes.ok) { const errorText = await recordRes.text(); @@ -233,16 +235,19 @@ async function handleKieMusicGeneration({ } const recordData = await recordRes.json(); - const state = String(recordData?.data?.status || "PENDING").toUpperCase(); + const state = String(recordData?.data?.status || recordData?.msg || "PENDING").toUpperCase(); - if (state === "SUCCESS") { + if (state === "SUCCESS" || state === "1" || state === "FINISHED") { const tracks = Array.isArray(recordData?.data?.response?.sunoData) ? recordData.data.response.sunoData : []; const audioFiles = tracks - .map((track) => track?.audioUrl) - .filter((url) => typeof url === "string" && url.length > 0) - .map((url) => ({ url, format: "mp3" })); + .map((track: unknown) => { + const t = track as Record; + return (typeof t?.audioUrl === "string" ? t.audioUrl : t?.url) as string; + }) + .filter((url: string) => typeof url === "string" && url.length > 0) + .map((url: string) => ({ url, format: "mp3" })); saveCallLog({ method: "POST", @@ -261,13 +266,18 @@ async function handleKieMusicGeneration({ } if ( - state.includes("FAILED") || + state.includes("FAIL") || state.includes("ERROR") || + state === "2" || + state === "3" || state === "CREATE_TASK_FAILED" || state === "GENERATE_AUDIO_FAILED" ) { const errorMessage = - recordData?.data?.errorMessage || recordData?.msg || "KIE music task failed"; + recordData?.data?.errorMessage || + recordData?.data?.failMsg || + recordData?.msg || + `KIE music task failed with status: ${state}`; return { success: false, status: 502, error: errorMessage }; } diff --git a/open-sse/handlers/videoGeneration.ts b/open-sse/handlers/videoGeneration.ts index f09b7f7274..15d6c570ac 100644 --- a/open-sse/handlers/videoGeneration.ts +++ b/open-sse/handlers/videoGeneration.ts @@ -318,16 +318,18 @@ async function handleKieVideoGeneration({ } const deadline = Date.now() + timeoutMs; + const statusBaseUrl = `${baseUrl}/api/v1/jobs/recordInfo`; + while (Date.now() < deadline) { - const recordRes = await fetch( - `${baseUrl}/api/v1/jobs/recordInfo?taskId=${encodeURIComponent(taskId)}`, - { - method: "GET", - headers: { - Authorization: `Bearer ${token}`, - }, - } - ); + const pollUrl = new URL(statusBaseUrl); + pollUrl.searchParams.set("taskId", String(taskId)); + + const recordRes = await fetch(pollUrl.toString(), { + method: "GET", + headers: { + Authorization: `Bearer ${token}`, + }, + }); if (!recordRes.ok) { const errorText = await recordRes.text(); @@ -335,10 +337,12 @@ async function handleKieVideoGeneration({ } const recordData = await recordRes.json(); - const state = String(recordData?.data?.state || "generating").toLowerCase(); + const state = String( + recordData?.data?.state || recordData?.data?.status || "generating" + ).toLowerCase(); - if (state === "success") { - let resultJson: any = {}; + if (state === "success" || state === "1" || state === "finished") { + let resultJson: Record = {}; try { resultJson = typeof recordData?.data?.resultJson === "string" @@ -351,10 +355,12 @@ async function handleKieVideoGeneration({ ? resultJson.resultUrls : Array.isArray(resultJson?.videoUrls) ? resultJson.videoUrls - : []; + : Array.isArray(recordData?.data?.response?.resultUrls) + ? recordData.data.response.resultUrls + : []; const videos = urls - .filter((url) => typeof url === "string" && url.length > 0) - .map((url) => ({ url, format: "mp4" })); + .filter((url: unknown) => typeof url === "string" && url.length > 0) + .map((url: unknown) => ({ url: url as string, format: "mp4" })); saveCallLog({ method: "POST", @@ -372,9 +378,21 @@ async function handleKieVideoGeneration({ }; } - if (state === "fail" || state === "failed" || state === "error" || state.includes("fail") || state.includes("error")) { + if ( + state === "fail" || + state === "failed" || + state === "error" || + state === "2" || + state === "3" || + state.includes("fail") || + state.includes("error") || + state.includes("failed") + ) { const errorMessage = - recordData?.data?.failMsg || recordData?.msg || "KIE video task failed"; + recordData?.data?.failMsg || + recordData?.data?.errorMessage || + recordData?.msg || + `KIE video task failed with state: ${state}`; return { success: false, status: 502, error: errorMessage }; }