From 302e1a571f495e06bf6151c981371de92d0c978a Mon Sep 17 00:00:00 2001 From: lapoaiscalers Date: Thu, 29 Jan 2026 17:31:58 +0100 Subject: [PATCH] fix: add required default parameters for Kie.ai models Some Kie.ai models (like gpt-image/1.5-text-to-image) require certain parameters to be present even if not user-specified (e.g., aspect_ratio, quality). Add getKieModelDefaults() function that provides model-specific defaults which are merged with user-provided parameters. Also skip file logging on Vercel since filesystem is read-only. Co-Authored-By: Claude Opus 4.5 --- src/app/api/generate/route.ts | 91 ++++++++++++++++++++++++++++++++++- src/utils/logger-server.ts | 18 +++++++ 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/src/app/api/generate/route.ts b/src/app/api/generate/route.ts index f87035c5..590a662c 100644 --- a/src/app/api/generate/route.ts +++ b/src/app/api/generate/route.ts @@ -1252,6 +1252,91 @@ async function generateWithFalQueue( // ============ Kie.ai Helpers ============ +/** + * Get default required parameters for a Kie model + * Many Kie models require specific parameters to be present even if not user-specified + */ +function getKieModelDefaults(modelId: string): Record { + switch (modelId) { + // GPT Image models require aspect_ratio and quality + case "gpt-image/1.5-text-to-image": + case "gpt-image/1.5-image-to-image": + return { + aspect_ratio: "1:1", + quality: "medium", + }; + + // Z-Image model + case "z-image": + return { + aspect_ratio: "1:1", + }; + + // Seedream models + case "seedream/4.5-text-to-image": + case "seedream/4.5-edit": + return { + aspect_ratio: "1:1", + }; + + // Nano Banana Pro (Kie's version) + case "nano-banana-pro": + return { + aspect_ratio: "1:1", + }; + + // Google Nano Banana models + case "google/nano-banana": + case "google/nano-banana-edit": + return { + aspect_ratio: "1:1", + }; + + // Sora video models + case "sora-2-text-to-video": + case "sora-2-image-to-video": + case "sora-2-pro-text-to-video": + case "sora-2-pro-image-to-video": + return { + aspect_ratio: "16:9", + duration: "5", + }; + + // Veo video models (use camelCase) + case "veo3": + case "veo3_fast": + return { + aspectRatio: "16:9", + }; + + // Bytedance Seedance + case "bytedance/seedance-1.5-pro": + return { + aspect_ratio: "16:9", + duration: "5", + }; + + // Kling video models + case "kling-2.6/text-to-video": + case "kling-2.6/image-to-video": + return { + aspect_ratio: "16:9", + duration: "5", + }; + + // Wan video models + case "wan/2-6-text-to-video": + case "wan/2-6-image-to-video": + return { + aspect_ratio: "16:9", + duration: "5", + }; + + default: + return {}; + } +} + /** * Get the correct image input parameter name for a Kie model */ @@ -1428,14 +1513,16 @@ async function generateWithKie( console.log(`[API:${requestId}] Kie.ai generation - Model: ${modelId}, Images: ${input.images?.length || 0}, Prompt: ${input.prompt.length} chars, Veo: ${isVeo}`); // Build the input object (all parameters go inside "input" for Kie API) - const inputParams: Record = {}; + // Start with model-specific required defaults + const modelDefaults = getKieModelDefaults(modelId); + const inputParams: Record = { ...modelDefaults }; // Add prompt if (input.prompt) { inputParams.prompt = input.prompt; } - // Add model parameters + // Add model parameters (user params override defaults) if (input.parameters) { Object.assign(inputParams, input.parameters); } diff --git a/src/utils/logger-server.ts b/src/utils/logger-server.ts index 548be69c..c6d2ff6a 100644 --- a/src/utils/logger-server.ts +++ b/src/utils/logger-server.ts @@ -7,10 +7,23 @@ import * as fs from 'fs/promises'; import * as path from 'path'; import type { LogSession } from './logger'; +/** + * Check if running on Vercel (read-only filesystem) + */ +function isVercelProduction(): boolean { + return !!process.env.VERCEL; +} + /** * Save session to file (server-side only) + * Note: Skipped on Vercel due to read-only filesystem */ export async function saveSession(session: LogSession): Promise { + if (isVercelProduction()) { + console.log(`[Logger] Skipping file save on Vercel (session: ${session.sessionId})`); + return; + } + const logsDir = path.join(process.cwd(), 'logs'); const filename = `session-${session.sessionId}.json`; const filepath = path.join(logsDir, filename); @@ -33,8 +46,13 @@ export async function saveSession(session: LogSession): Promise { /** * Rotate log files (keep only last 10 sessions) + * Note: Skipped on Vercel due to read-only filesystem */ export async function rotateLogFiles(): Promise { + if (isVercelProduction()) { + return; + } + const logsDir = path.join(process.cwd(), 'logs'); // Ensure logs directory exists