import type { CanvasAgentContext } from "@/types/canvas/agent-protocol"; function trimText(value: unknown, maxLength: number) { return typeof value === "string" ? value.trim().slice(0, maxLength) : ""; } function uniqueStrings(values: Array) { return Array.from( new Set(values.map((value) => trimText(value, 160)).filter(Boolean)) ); } export function hasCanvasAgentAnnotationEditIntent(userText: string) { const text = trimText(userText, 1000); if (!text) return false; const annotationKeyword = "(?:批注|标注|箭头|框选|圈选|备注|annotation|note)"; if (new RegExp(`(?:添加|新增|创建|加|写).{0,8}${annotationKeyword}`, "i").test(text)) { return false; } return ( new RegExp(`(?:按|按照|根据|依据|依照|参考|基于).{0,18}${annotationKeyword}`, "i").test( text ) || new RegExp( `${annotationKeyword}.{0,24}(?:修改|编辑|修图|改图|处理|调整|去掉|移除|换|生成|出图|执行)`, "i" ).test(text) ); } export function buildCanvasAgentAnnotationEditPrompt(params: { context?: CanvasAgentContext | null; targetNodeIds?: string[]; userText: string; maxAnnotations?: number; }) { const context = params.context; if (!context || !hasCanvasAgentAnnotationEditIntent(params.userText)) { return ""; } const targetNodeIds = uniqueStrings([ ...(params.targetNodeIds || []), ...context.selectedNodeIds, ...context.selectedNodes.filter((node) => node.isSelected).map((node) => node.nodeId), ]); if (targetNodeIds.length === 0) return ""; const targetSet = new Set(targetNodeIds); const annotations = context.annotations .filter((annotation) => targetSet.has(annotation.sourceNodeId)) .slice(0, Math.max(1, params.maxAnnotations || 8)); if (annotations.length === 0) return ""; const lines = annotations.map((annotation, index) => { const parts = [ `${index + 1}. 节点 ${annotation.sourceNodeId}`, `类型 ${annotation.type}`, annotation.text ? `说明:${annotation.text}` : "", annotation.bounds ? `框选区域:x=${annotation.bounds.x}, y=${annotation.bounds.y}, width=${annotation.bounds.width}, height=${annotation.bounds.height}` : "", annotation.targetPoint ? `目标点:x=${annotation.targetPoint.x}, y=${annotation.targetPoint.y}` : "", ].filter(Boolean); return parts.join(";"); }); return [ "【画布批注编辑要求】用户要求按画布批注/标注执行编辑。请把以下批注作为本轮编辑的主要约束:", ...lines, "执行要求:优先修改批注指向或框选的区域;未被批注要求修改的主体、背景、构图与文字尽量保持不变;如果批注文字与用户当前文字冲突,以用户当前文字为准。", ].join("\n"); }