diff --git a/app/(chat)/api/chat/route.ts b/app/(chat)/api/chat/route.ts index 769de525a..5c3f8a432 100644 --- a/app/(chat)/api/chat/route.ts +++ b/app/(chat)/api/chat/route.ts @@ -251,6 +251,17 @@ function startStreamKeepalive(writer: StreamWriter, label: string, intervalMs = type VideoModeType = "text-to-video" | "first-frame" | "first-last-frame" | "reference-images"; +const VIDEO_PROVIDER_TYPES = new Set([ + "volcano-video", + "doubao-video", + "qianwen-video", + "fal-video", +]); + +function isVideoProviderType(providerType?: string | null): boolean { + return Boolean(providerType && VIDEO_PROVIDER_TYPES.has(providerType)); +} + function inferSupportedVideoModesByModelId(modelId: string): VideoModeType[] { const normalized = modelId.toLowerCase(); @@ -1438,6 +1449,7 @@ export async function POST(request: Request) { // 🆕 存储智能模式的相关信息 let smartAutoFriendlyMessage: string | undefined; // AI的自然对话回复 let smartAutoOptimizedPrompt: string | undefined; // 优化后的提示词(不修改用户消息,只用于API调用) + let smartAutoPromptFromVideoPlan = false; let smartAutoRecommendedImageParams: AgentRecommendedImageParams | undefined; let smartAutoVideoPlan: AgentVideoPlan | undefined; let smartAutoRecommendedVideoParams: AgentRecommendedVideoParams | undefined; @@ -1448,6 +1460,7 @@ export async function POST(request: Request) { let shouldRunAgentConversation = finalModelId === "auto"; let shouldKeepSelectedModel = false; const requestedModelId = selectedChatModel; + let requestedModelProviderType: string | undefined; if (!shouldRunAgentConversation && requestedModelId !== "auto") { const selectedModelIsUUID = @@ -1475,6 +1488,8 @@ export async function POST(request: Request) { selectedModelProviderType = selectedProvider?.type as string | undefined; } + requestedModelProviderType = selectedModelProviderType; + if (selectedModelConfig) { const fixedImageProviderTypes = new Set([ "gemini", @@ -1484,17 +1499,11 @@ export async function POST(request: Request) { "fal-image", "volcano-vision", ]); - const fixedVideoProviderTypes = new Set([ - "volcano-video", - "doubao-video", - "qianwen-video", - "fal-video", - ]); const isFixedVisualModel = !selectedModelConfig.isSubModel && (selectedModelConfig.supportsImageGen || (selectedModelProviderType - ? fixedVideoProviderTypes.has(selectedModelProviderType) + ? isVideoProviderType(selectedModelProviderType) : false) || (selectedModelProviderType ? fixedImageProviderTypes.has(selectedModelProviderType) @@ -1516,6 +1525,9 @@ export async function POST(request: Request) { } } + const allowAgentVideoGeneration = + Boolean(requestBody.videoParams) || isVideoProviderType(requestedModelProviderType); + // ========== Smart Auto Mode Logic ========== if (shouldRunAgentConversation) { console.log("[Smart Auto Mode] 🚀 Starting intelligent analysis..."); @@ -1770,6 +1782,7 @@ export async function POST(request: Request) { smartAutoRecommendedVideoParams = autoGraphResult.videoPlan.recommendedVideoParams; if (!smartAutoOptimizedPrompt && autoGraphResult.videoPlan.finalPrompt?.trim()) { smartAutoOptimizedPrompt = autoGraphResult.videoPlan.finalPrompt.trim(); + smartAutoPromptFromVideoPlan = true; } console.log("[Smart Auto Mode] 🎬 Agent video plan ready:", { hasScript: Boolean(autoGraphResult.videoPlan.script), @@ -1784,8 +1797,49 @@ export async function POST(request: Request) { } if (autoGraphResult.route && !shouldKeepSelectedModel) { - finalModelId = autoGraphResult.route.id; - console.log(`[Smart Auto Mode] ✅ Routed to: ${autoGraphResult.route.displayName} (${autoGraphResult.route.reason})`); + const routeIsVideo = isVideoProviderType(autoGraphResult.route.providerType); + if (routeIsVideo && !allowAgentVideoGeneration) { + const fallbackIntent: "image_edit" | "image_gen" = hasImage ? "image_edit" : "image_gen"; + smartAutoDetectedIntent = fallbackIntent; + smartAutoVideoPlan = undefined; + smartAutoRecommendedVideoParams = undefined; + if (smartAutoPromptFromVideoPlan) { + smartAutoOptimizedPrompt = textContent.trim() || undefined; + smartAutoPromptFromVideoPlan = false; + } + smartAutoFriendlyMessage = + smartAutoFriendlyMessage && !/视频/.test(smartAutoFriendlyMessage) + ? smartAutoFriendlyMessage + : "当前 Agent 默认按图片任务执行;如需生成视频,请先手动切换到“视频”模式。"; + console.log( + `[Smart Auto Mode] 🚫 Blocked auto video route (${autoGraphResult.route.displayName}), fallback to ${fallbackIntent}`, + ); + try { + const { routeToModel } = await import("@/lib/ai/model-router"); + const fallbackRoute = await routeToModel({ + intent: fallbackIntent, + subIntent: autoGraphResult.analysis?.subIntent, + hasImage, + }); + if (!isVideoProviderType(fallbackRoute.providerType)) { + finalModelId = fallbackRoute.id; + console.log( + `[Smart Auto Mode] ✅ Fallback routed to: ${fallbackRoute.displayName} (${fallbackRoute.reason})`, + ); + } else { + console.warn( + `[Smart Auto Mode] ⚠️ Fallback route still video (${fallbackRoute.displayName}), keep previous model`, + ); + } + } catch (fallbackRouteError) { + console.error("[Smart Auto Mode] Failed to resolve non-video fallback route:", fallbackRouteError); + } + } else { + finalModelId = autoGraphResult.route.id; + console.log( + `[Smart Auto Mode] ✅ Routed to: ${autoGraphResult.route.displayName} (${autoGraphResult.route.reason})`, + ); + } } else if (autoGraphResult.route && shouldKeepSelectedModel) { finalModelId = requestedModelId; console.log("[Smart Auto Mode] 🔒 Keep user-selected model, skip routing override"); @@ -1943,6 +1997,7 @@ export async function POST(request: Request) { const shouldApplyAgentVideoParams = shouldRunAgentConversation && !smartAutoNeedsClarification && + allowAgentVideoGeneration && smartAutoDetectedIntent === "video_gen"; const effectiveImageParams = shouldApplyAgentImageParams ? mergeImageParamsWithAgentRecommendation({ @@ -3528,9 +3583,14 @@ export async function POST(request: Request) { }); activeTools.push("requestSuggestions"); } - if (enabledTools.includes("generateVideo")) { + const shouldEnableGenerateVideoTool = + enabledTools.includes("generateVideo") && + (!shouldRunAgentConversation || allowAgentVideoGeneration); + if (shouldEnableGenerateVideoTool) { tools.generateVideo = generateVideo({ dataStream }); activeTools.push("generateVideo"); + } else if (enabledTools.includes("generateVideo") && shouldRunAgentConversation) { + console.log("[Smart Auto Mode] 🚫 generateVideo tool disabled (manual video mode not selected)"); } console.log("[Chat API] Calling streamText with model:", (languageModel as any).modelId, (languageModel as any).provider); // 调试日志