import type { DirectAgentToolCapability } from "@/lib/ai/runtime/direct-agent-execution"; export type CanvasAgentComposerMode = "agent" | "image" | "video" | "detail" | "clawd"; export type CanvasAgentEntryMode = "auto" | "preset"; export interface CanvasAgentRequestPolicy { effectiveSelectedChatModel: string; shouldForceToolOrchestration: boolean; reason: string | null; } export interface CanvasAgentTargetPreference { shouldPreferLatestResult: boolean; shouldPreferWorkingMemoryTarget: boolean; confidence: number; reason: string | null; } const DEICTIC_TARGET_REGEX = /(这张图|这只|这个|这款|这套|当前这张|当前这个|当前这只|这一张|这一只|这个产品|这个物体|这只猫|这只狗)/i; const ACTIONABLE_IMAGE_EDIT_REGEX = /(抠图|去背景|透明背景|去背|扣图|抠出|扣出|抠出来|扣出来|移除背景|去水印|水印|去logo|去\s*logo|移除logo|去除logo|换背景|改背景|背景换成|背景改成|白底|纯色背景|替换.*背景|变清晰|高清|锐化|降噪|提升质量|修复|清晰化|扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|多视角|换视角|改视角|视角变体|新角度|换角度|改角度|去除|消除|擦掉|删除|移除|p掉|重绘|风格化|卡通化|动漫风|油画风|调色|调整颜色|亮度|对比度|饱和度|缩放|放大|缩小|调整尺寸|裁剪|resize|crop|修图|p图|改图|调图|编辑.*图|优化.*图|重做|再调整|继续改|继续调|处理)/i; export function normalizeCanvasAgentRequestText(text: string) { return String(text || "").toLowerCase().replace(/\s+/g, "").trim(); } export function hasCanvasAgentDeicticTarget(text: string) { return DEICTIC_TARGET_REGEX.test(String(text || "")); } export function hasCanvasAgentActionableImageEditIntent(text: string) { return ACTIONABLE_IMAGE_EDIT_REGEX.test(String(text || "")); } export function inferCanvasAgentImageEditCapability( text: string, ): DirectAgentToolCapability | null { const normalizedText = normalizeCanvasAgentRequestText(text); if (!normalizedText) return null; if (/去水印|水印|去logo|移除logo|去除logo/.test(normalizedText)) { return "remove_watermark"; } if (/抠图|去背景|透明背景|去背|扣图|抠出|扣出|抠出来|扣出来|移除背景/.test(normalizedText)) { return "remove_background"; } if (/多视角|换视角|改视角|视角变体|新角度|换角度|改角度|侧面|侧视|背面|背后|俯视|俯拍|仰视|仰拍|低机位|高机位/.test(normalizedText)) { return "angle_variant"; } if (/扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|比例|画幅|竖版|横版|竖图|横图|9:16|16:9|1:1/.test(normalizedText)) { return "extend"; } if (/调整尺寸|裁剪|resize|crop|缩放|放大|缩小/.test(normalizedText)) { return "resize"; } if (/局部|框选|选区|区域|涂抹|蒙版/.test(normalizedText)) { return "local_edit"; } if (/高清|清晰|锐化|降噪|提升质量|修复|清晰化/.test(normalizedText)) { return "enhance"; } if (hasCanvasAgentActionableImageEditIntent(text)) { return "generic_edit"; } return null; } export function resolveCanvasAgentRequestPolicy(params: { composerMode?: string | null; agentEntryMode?: string | null; selectedChatModel?: string | null; hasCanvasControlIntentFastPath?: boolean; }): CanvasAgentRequestPolicy { const composerMode = String(params.composerMode || "").trim(); const agentEntryMode = String(params.agentEntryMode || "").trim(); const selectedChatModel = String(params.selectedChatModel || "").trim() || "auto"; const isAgentAutoComposer = composerMode === "agent" && agentEntryMode !== "preset"; const shouldForceToolOrchestration = isAgentAutoComposer || Boolean(params.hasCanvasControlIntentFastPath); if (isAgentAutoComposer) { return { effectiveSelectedChatModel: "auto", shouldForceToolOrchestration: true, reason: "agent_auto_composer", }; } if (params.hasCanvasControlIntentFastPath) { return { effectiveSelectedChatModel: selectedChatModel, shouldForceToolOrchestration: true, reason: "canvas_control_fast_path", }; } return { effectiveSelectedChatModel: selectedChatModel, shouldForceToolOrchestration, reason: null, }; } export function resolveCanvasAgentTargetPreference(params: { text: string; selectedImageCount: number; latestResultImageCount: number; workingMemoryTargetImageCount: number; }): CanvasAgentTargetPreference { const hasDeicticTarget = hasCanvasAgentDeicticTarget(params.text); const hasEditIntent = hasCanvasAgentActionableImageEditIntent(params.text); const selectedImageCount = Math.max(0, Math.round(params.selectedImageCount || 0)); const latestResultImageCount = Math.max( 0, Math.round(params.latestResultImageCount || 0), ); const workingMemoryTargetImageCount = Math.max( 0, Math.round(params.workingMemoryTargetImageCount || 0), ); if (!hasDeicticTarget || !hasEditIntent || selectedImageCount > 0) { return { shouldPreferLatestResult: false, shouldPreferWorkingMemoryTarget: false, confidence: 0, reason: null, }; } if (latestResultImageCount > 0) { return { shouldPreferLatestResult: true, shouldPreferWorkingMemoryTarget: false, confidence: 90, reason: "deictic_edit_prefers_latest_result", }; } if (workingMemoryTargetImageCount > 0) { return { shouldPreferLatestResult: false, shouldPreferWorkingMemoryTarget: true, confidence: 86, reason: "deictic_edit_uses_working_memory_target", }; } return { shouldPreferLatestResult: false, shouldPreferWorkingMemoryTarget: false, confidence: 0, reason: null, }; }