Browse Source

feat: add client-side polling to nanoBanana, audio, and 3D executors

All executors that call /api/generate now check for the polling flag
and enter the pollGenerateTask loop for long-running Kie tasks.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 3 months ago
parent
commit
e7145199cd
  1. 24
      src/store/execution/generate3dExecutor.ts
  2. 25
      src/store/execution/generateAudioExecutor.ts
  3. 24
      src/store/execution/nanoBananaExecutor.ts

24
src/store/execution/generate3dExecutor.ts

@ -7,6 +7,7 @@
import type { Generate3DNodeData } from "@/types";
import { buildGenerateHeaders } from "@/store/utils/buildApiHeaders";
import { pollGenerateTask } from "./pollTaskCompletion";
import type { NodeExecutionContext } from "./types";
export interface Generate3DOptions {
@ -106,7 +107,28 @@ export async function executeGenerate3D(
throw new Error(errorMessage);
}
const result = await response.json();
let result = await response.json();
// Handle polling response (long-running Kie tasks)
if (result.polling) {
result = await pollGenerateTask({
taskId: result.taskId,
provider: result.pollProvider,
modelId: result.pollModelId,
modelName: result.pollModelName,
mediaType: result.pollMediaType,
headers,
signal,
});
if (!result.success) {
updateNodeData(node.id, {
status: "error",
error: result.error || "3D generation failed",
});
throw new Error(result.error || "3D generation failed");
}
}
if (result.success && result.model3dUrl) {
updateNodeData(node.id, {

25
src/store/execution/generateAudioExecutor.ts

@ -7,6 +7,7 @@
import type { GenerateAudioNodeData } from "@/types";
import { buildGenerateHeaders } from "@/store/utils/buildApiHeaders";
import { pollGenerateTask } from "./pollTaskCompletion";
import type { NodeExecutionContext } from "./types";
export interface GenerateAudioOptions {
@ -118,7 +119,29 @@ export async function executeGenerateAudio(
throw new Error(errorMessage);
}
const result = await response.json();
let result = await response.json();
// Handle polling response (long-running Kie tasks)
if (result.polling) {
result = await pollGenerateTask({
taskId: result.taskId,
provider: result.pollProvider,
modelId: result.pollModelId,
modelName: result.pollModelName,
mediaType: result.pollMediaType,
headers,
signal,
});
if (!result.success) {
updateNodeData(node.id, {
status: "error",
error: result.error || "Audio generation failed",
});
errorHandled = true;
throw new Error(result.error || "Audio generation failed");
}
}
// Handle audio response (audio or audioUrl field)
const audioData = result.audio || result.audioUrl;

24
src/store/execution/nanoBananaExecutor.ts

@ -10,6 +10,7 @@ import type {
} from "@/types";
import { calculateGenerationCost } from "@/utils/costCalculator";
import { buildGenerateHeaders } from "@/store/utils/buildApiHeaders";
import { pollGenerateTask } from "./pollTaskCompletion";
import type { NodeExecutionContext } from "./types";
export interface NanoBananaOptions {
@ -141,7 +142,28 @@ export async function executeNanoBanana(
throw new Error(errorMessage);
}
const result = await response.json();
let result = await response.json();
// Handle polling response (long-running Kie tasks)
if (result.polling) {
result = await pollGenerateTask({
taskId: result.taskId,
provider: result.pollProvider,
modelId: result.pollModelId,
modelName: result.pollModelName,
mediaType: result.pollMediaType,
headers,
signal,
});
if (!result.success) {
updateNodeData(node.id, {
status: "error",
error: result.error || "Generation failed",
});
throw new Error(result.error || "Generation failed");
}
}
if (result.success && result.image) {
const timestamp = Date.now();

Loading…
Cancel
Save