feat: route canvas agent watermark removal
This commit is contained in:
parent
9151058d79
commit
0afa404b19
@ -77,6 +77,7 @@ export type AgentPreferredCapability =
|
||||
| "analyze"
|
||||
| "generic_edit"
|
||||
| "remove_background"
|
||||
| "remove_watermark"
|
||||
| "enhance"
|
||||
| "extend"
|
||||
| "resize"
|
||||
@ -246,6 +247,7 @@ function inferPreferredCapability(
|
||||
tool.name !== "useOriginalUploadImage"
|
||||
)?.name || toolCalls?.[0]?.name;
|
||||
if (firstTool === "removeBackground") return "remove_background";
|
||||
if (firstTool === "removeWatermark") return "remove_watermark";
|
||||
if (firstTool === "enhanceImage") return "enhance";
|
||||
if (firstTool === "extendImage") return "extend";
|
||||
if (firstTool === "resizeImage") return "resize";
|
||||
@ -263,6 +265,8 @@ function inferPreferredCapability(
|
||||
switch (analysis.subIntent) {
|
||||
case "remove_background":
|
||||
return "remove_background";
|
||||
case "remove_watermark":
|
||||
return "remove_watermark";
|
||||
case "enhance":
|
||||
return "enhance";
|
||||
case "extend":
|
||||
@ -1395,6 +1399,7 @@ function sanitizeAgentPlan(
|
||||
"analyze",
|
||||
"generic_edit",
|
||||
"remove_background",
|
||||
"remove_watermark",
|
||||
"enhance",
|
||||
"extend",
|
||||
"resize",
|
||||
@ -1567,7 +1572,7 @@ async function buildExecutionPlanWithAgent(
|
||||
- respond:纯对话、策略讨论、解释说明、普通问答
|
||||
- clarify:信息不足,需要先澄清
|
||||
- analyze_image:用户要你看图、识图、评估、分析、给建议
|
||||
- edit_image:基于当前图/历史图做修改、抠图、增强、换背景、调色、尺寸调整、局部重绘
|
||||
- edit_image:基于当前图/历史图做修改、抠图、去水印、增强、换背景、调色、尺寸调整、局部重绘
|
||||
- generate_image:生成新图
|
||||
- generate_video:生成视频
|
||||
|
||||
@ -1579,7 +1584,7 @@ async function buildExecutionPlanWithAgent(
|
||||
5. 优先保持一次只选择一个主工具;toolCalls 只从提供的工具列表里选。
|
||||
6. shouldUseStructuredReply 只在 edit_image / generate_image / generate_video 时设为 true。
|
||||
7. targetSource 要忠实反映当前目标图来源:explicit_selection/current_upload/text_reference/working_memory/latest_result/clarification/none。
|
||||
8. preferredCapability 要尽量具体,例如 remove_background / enhance / extend / resize / box_cutout / publish_canvas。
|
||||
8. preferredCapability 要尽量具体,例如 remove_background / remove_watermark / enhance / extend / resize / box_cutout / publish_canvas。
|
||||
9. 必须优先使用新的强语义工具名:resolveTargetImage / analyzeTargetImage / editTargetImage / generateNewImage / publishResultToCanvas。
|
||||
10. 必须遵守当前专家路由约束;如果约束要求纯对话,则绝不能输出 generate_image / edit_image / generate_video。
|
||||
|
||||
@ -1590,7 +1595,7 @@ async function buildExecutionPlanWithAgent(
|
||||
"intent": "chat|vision|image_edit|image_gen|video_gen",
|
||||
"subIntent": "可选,仅 image_edit 时填写",
|
||||
"targetSource": "explicit_selection|current_upload|text_reference|working_memory|latest_result|clarification|none",
|
||||
"preferredCapability": "respond|analyze|generic_edit|remove_background|enhance|extend|resize|box_cutout|generate_image|generate_video|publish_canvas",
|
||||
"preferredCapability": "respond|analyze|generic_edit|remove_background|remove_watermark|enhance|extend|resize|box_cutout|generate_image|generate_video|publish_canvas",
|
||||
"responseMode": "direct_answer|tool_then_answer|tool_then_execute|clarify",
|
||||
"shouldUseHistoryImage": true,
|
||||
"shouldUseStructuredReply": false,
|
||||
|
||||
@ -66,6 +66,7 @@ export function buildImageEditSpecialistRoute(params: {
|
||||
"editTargetImage",
|
||||
"editImage",
|
||||
"removeBackground",
|
||||
"removeWatermark",
|
||||
"enhanceImage",
|
||||
"extendImage",
|
||||
"resizeImage",
|
||||
|
||||
@ -12,6 +12,7 @@ export type DirectAgentToolCapability =
|
||||
| "analyze"
|
||||
| "generic_edit"
|
||||
| "remove_background"
|
||||
| "remove_watermark"
|
||||
| "enhance"
|
||||
| "resize"
|
||||
| "extend"
|
||||
@ -23,6 +24,7 @@ export type DirectAgentToolName =
|
||||
| "analyzeImage"
|
||||
| "editImage"
|
||||
| "removeBackground"
|
||||
| "removeWatermark"
|
||||
| "enhanceImage"
|
||||
| "resizeImage"
|
||||
| "extendImage"
|
||||
@ -88,6 +90,8 @@ function mapDirectToolNameToCapability(
|
||||
return "generic_edit";
|
||||
case "removeBackground":
|
||||
return "remove_background";
|
||||
case "removeWatermark":
|
||||
return "remove_watermark";
|
||||
case "enhanceImage":
|
||||
return "enhance";
|
||||
case "resizeImage":
|
||||
@ -171,6 +175,35 @@ export function resolveDirectAgentToolExecution(
|
||||
const toolNames = mergedToolCalls.map((tool) => String(tool.name || ""));
|
||||
const toolNameSet = new Set(toolNames);
|
||||
const hasToolCall = (toolName: string) => toolNameSet.has(toolName);
|
||||
const preferredSpecificImageEditTool = (() => {
|
||||
const preferredCapability = execution?.preferredCapability || plan?.preferredCapability;
|
||||
const routeSubIntent = execution?.routeSubIntent || plan?.subIntent;
|
||||
if (
|
||||
preferredCapability === "remove_background" ||
|
||||
routeSubIntent === "remove_background"
|
||||
) {
|
||||
return "removeBackground";
|
||||
}
|
||||
if (
|
||||
preferredCapability === "remove_watermark" ||
|
||||
routeSubIntent === "remove_watermark"
|
||||
) {
|
||||
return "removeWatermark";
|
||||
}
|
||||
if (preferredCapability === "enhance" || routeSubIntent === "enhance") {
|
||||
return "enhanceImage";
|
||||
}
|
||||
if (preferredCapability === "resize" || routeSubIntent === "resize") {
|
||||
return "resizeImage";
|
||||
}
|
||||
if (preferredCapability === "extend" || routeSubIntent === "extend") {
|
||||
return "extendImage";
|
||||
}
|
||||
if (preferredCapability === "box_cutout" || routeSubIntent === "box_cutout") {
|
||||
return "boxCutout";
|
||||
}
|
||||
return null;
|
||||
})();
|
||||
const sourceTools = toolNames.filter((toolName): toolName is DirectAgentSourceToolName =>
|
||||
toolName === "useSelectedCanvasImage" ||
|
||||
toolName === "useLatestResultImage" ||
|
||||
@ -211,21 +244,23 @@ export function resolveDirectAgentToolExecution(
|
||||
? "analyzeImage"
|
||||
: hasToolCall("removeBackground")
|
||||
? "removeBackground"
|
||||
: hasToolCall("enhanceImage")
|
||||
? "enhanceImage"
|
||||
: hasToolCall("resizeImage")
|
||||
? "resizeImage"
|
||||
: hasToolCall("extendImage")
|
||||
? "extendImage"
|
||||
: hasToolCall("boxCutout")
|
||||
? "boxCutout"
|
||||
: hasToolCall("editTargetImage") || hasToolCall("editImage")
|
||||
? "editImage"
|
||||
: hasToolCall("generateNewImage") || hasToolCall("generateImage")
|
||||
? "generateImage"
|
||||
: hasToolCall("generateVideo")
|
||||
? "generateVideo"
|
||||
: null) ||
|
||||
: hasToolCall("removeWatermark")
|
||||
? "removeWatermark"
|
||||
: hasToolCall("enhanceImage")
|
||||
? "enhanceImage"
|
||||
: hasToolCall("resizeImage")
|
||||
? "resizeImage"
|
||||
: hasToolCall("extendImage")
|
||||
? "extendImage"
|
||||
: hasToolCall("boxCutout")
|
||||
? "boxCutout"
|
||||
: hasToolCall("editTargetImage") || hasToolCall("editImage")
|
||||
? preferredSpecificImageEditTool || "editImage"
|
||||
: hasToolCall("generateNewImage") || hasToolCall("generateImage")
|
||||
? "generateImage"
|
||||
: hasToolCall("generateVideo")
|
||||
? "generateVideo"
|
||||
: null) ||
|
||||
(() => {
|
||||
if (
|
||||
execution?.preferredCapability === "analyze" ||
|
||||
@ -240,6 +275,12 @@ export function resolveDirectAgentToolExecution(
|
||||
) {
|
||||
return "removeBackground";
|
||||
}
|
||||
if (
|
||||
execution?.preferredCapability === "remove_watermark" ||
|
||||
execution?.routeSubIntent === "remove_watermark"
|
||||
) {
|
||||
return "removeWatermark";
|
||||
}
|
||||
if (
|
||||
execution?.preferredCapability === "enhance" ||
|
||||
execution?.routeSubIntent === "enhance"
|
||||
@ -325,6 +366,7 @@ export function isDirectAgentImageEditToolName(
|
||||
| "editImage"
|
||||
| "enhanceImage"
|
||||
| "removeBackground"
|
||||
| "removeWatermark"
|
||||
| "resizeImage"
|
||||
| "extendImage"
|
||||
| "boxCutout" {
|
||||
@ -332,6 +374,7 @@ export function isDirectAgentImageEditToolName(
|
||||
case "editImage":
|
||||
case "enhanceImage":
|
||||
case "removeBackground":
|
||||
case "removeWatermark":
|
||||
case "resizeImage":
|
||||
case "extendImage":
|
||||
case "boxCutout":
|
||||
@ -349,6 +392,8 @@ export function getDirectAgentToolLabel(capability: DirectAgentToolCapability):
|
||||
return "Agent工具:图片编辑";
|
||||
case "remove_background":
|
||||
return "Agent工具:抠图";
|
||||
case "remove_watermark":
|
||||
return "Agent工具:去水印";
|
||||
case "enhance":
|
||||
return "Agent工具:图像增强";
|
||||
case "resize":
|
||||
@ -392,6 +437,8 @@ export function getDirectAgentToolSuccessMessage(
|
||||
return "已完成图片编辑,结果如下:";
|
||||
case "remove_background":
|
||||
return "已完成抠图处理,结果如下:";
|
||||
case "remove_watermark":
|
||||
return "已完成去水印处理,结果如下:";
|
||||
case "enhance":
|
||||
return "已完成图像增强,结果如下:";
|
||||
case "resize":
|
||||
@ -419,6 +466,8 @@ export function getDirectAgentToolTargetMissingMessage(
|
||||
return "请先上传或选中一张图片,我才能继续帮你修改。";
|
||||
case "remove_background":
|
||||
return "请先上传或选中一张图片,我才能继续帮你执行抠图。";
|
||||
case "remove_watermark":
|
||||
return "请先上传或选中一张图片,我才能继续帮你去水印。";
|
||||
case "enhance":
|
||||
return "请先上传或选中一张图片,我才能继续帮你做图像增强。";
|
||||
case "resize":
|
||||
@ -455,6 +504,8 @@ export function getDirectAgentToolErrorMessage(
|
||||
return `图片编辑暂时失败:${detail}`;
|
||||
case "remove_background":
|
||||
return `抠图暂时失败:${detail}`;
|
||||
case "remove_watermark":
|
||||
return `去水印暂时失败:${detail}`;
|
||||
case "enhance":
|
||||
return `图像增强暂时失败:${detail}`;
|
||||
case "resize":
|
||||
|
||||
@ -141,6 +141,37 @@ async function executeDirectAgentEnhanceJob(params: {
|
||||
};
|
||||
}
|
||||
|
||||
async function executeDirectAgentWatermarkRemoveJob(params: {
|
||||
requestUrl: string;
|
||||
requestHeaders: Headers;
|
||||
imageUrl: string;
|
||||
}) {
|
||||
const endpoint = new URL("/api/watermark-remove", params.requestUrl).toString();
|
||||
const cookieHeader = params.requestHeaders.get("cookie") || "";
|
||||
const result = await requestLongTaskResult({
|
||||
endpoint,
|
||||
payload: {
|
||||
image_url: params.imageUrl,
|
||||
},
|
||||
timeoutMs: 20 * 60 * 1000,
|
||||
headers: cookieHeader
|
||||
? {
|
||||
cookie: cookieHeader,
|
||||
}
|
||||
: undefined,
|
||||
});
|
||||
|
||||
if (!result?.success || !result?.original_url) {
|
||||
throw new Error(String(result?.error || result?.detail || "去水印失败"));
|
||||
}
|
||||
|
||||
return {
|
||||
originalUrl: String(result.original_url),
|
||||
thumbnailUrl: String(result.thumbnail_url || result.original_url),
|
||||
imageSize: "2K",
|
||||
};
|
||||
}
|
||||
|
||||
export function isDirectAgentImageEditServiceError(error: unknown) {
|
||||
return (
|
||||
error instanceof RmbgServiceError ||
|
||||
@ -315,6 +346,23 @@ export async function executeDirectAgentImageEditTool(
|
||||
});
|
||||
}
|
||||
|
||||
if (params.capability === "remove_watermark") {
|
||||
const result = await executeDirectAgentWatermarkRemoveJob({
|
||||
requestUrl: params.requestUrl,
|
||||
requestHeaders: params.requestHeaders,
|
||||
imageUrl: params.sourceImageUrl,
|
||||
});
|
||||
|
||||
return finalizeDirectAgentImageEditResult({
|
||||
userId: params.userId,
|
||||
capability: params.capability,
|
||||
originalUrl: result.originalUrl,
|
||||
thumbnailUrl: result.thumbnailUrl,
|
||||
imageSize: result.imageSize,
|
||||
mediaAssetId: null,
|
||||
});
|
||||
}
|
||||
|
||||
if (params.capability === "resize") {
|
||||
const plannedArgs = findAgentToolCallArgs(
|
||||
"resizeImage",
|
||||
|
||||
@ -18,6 +18,7 @@ export type IntentArbiterPreferredCapability =
|
||||
| "analyze"
|
||||
| "generic_edit"
|
||||
| "remove_background"
|
||||
| "remove_watermark"
|
||||
| "enhance"
|
||||
| "extend"
|
||||
| "resize"
|
||||
@ -113,13 +114,14 @@ function isExplicitImageGenerationRequest(text: string): boolean {
|
||||
|
||||
function isLikelyImageEditRequest(text: string): boolean {
|
||||
const normalizedText = String(text || "").toLowerCase();
|
||||
return /抠图|去背景|透明背景|去背|扣图|移除背景|换背景|改背景|背景换成|背景改成|白底|纯色背景|替换.*背景|变清晰|高清|锐化|降噪|提升质量|修复|清晰化|扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|换成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|改成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|比例|画幅|竖版|横版|去除|消除|擦掉|删除|移除|p掉|重绘|风格化|卡通化|动漫风|油画风|转.*风格|变.*风格|改.*风格|调色|调整颜色|亮度|对比度|饱和度|色调|曝光|滤镜|改成.*色|换成.*色|变成.*色|颜色改成|颜色换成|颜色变成|缩放|放大|缩小|调整尺寸|裁剪|resize|crop|修图|p图|改图|调图|编辑.*图|优化.*图|重做|再调整|继续改|继续调/.test(
|
||||
return /抠图|去背景|透明背景|去背|扣图|移除背景|去水印|水印|去logo|去\s*logo|移除logo|去除logo|换背景|改背景|背景换成|背景改成|白底|纯色背景|替换.*背景|变清晰|高清|锐化|降噪|提升质量|修复|清晰化|扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|换成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|改成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|比例|画幅|竖版|横版|去除|消除|擦掉|删除|移除|p掉|重绘|风格化|卡通化|动漫风|油画风|转.*风格|变.*风格|改.*风格|调色|调整颜色|亮度|对比度|饱和度|色调|曝光|滤镜|改成.*色|换成.*色|变成.*色|颜色改成|颜色换成|颜色变成|缩放|放大|缩小|调整尺寸|裁剪|resize|crop|修图|p图|改图|调图|编辑.*图|优化.*图|重做|再调整|继续改|继续调/.test(
|
||||
normalizedText,
|
||||
);
|
||||
}
|
||||
|
||||
function inferDefaultImageEditSubIntent(text: string): string {
|
||||
const lowerText = String(text || "").toLowerCase();
|
||||
if (/去水印|水印|去logo|去\s*logo|移除logo|去除logo/.test(lowerText)) return "remove_watermark";
|
||||
if (/抠图|去背景|透明背景|去背|扣图|移除背景/.test(lowerText)) return "remove_background";
|
||||
if (/换背景|改背景|背景换成|背景改成|白底|透明底/.test(lowerText)) return "replace_background";
|
||||
if (/扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|比例|画幅|竖版|横版|竖图|横图|9:16|16:9|1:1/.test(lowerText)) return "extend";
|
||||
@ -161,6 +163,8 @@ function mapPreferredCapability(
|
||||
switch (subIntent) {
|
||||
case "remove_background":
|
||||
return "remove_background";
|
||||
case "remove_watermark":
|
||||
return "remove_watermark";
|
||||
case "extend":
|
||||
return "extend";
|
||||
case "resize":
|
||||
|
||||
@ -106,6 +106,7 @@ export function routeAgentSkill(
|
||||
"editTargetImage",
|
||||
"editImage",
|
||||
"removeBackground",
|
||||
"removeWatermark",
|
||||
"enhanceImage",
|
||||
"extendImage",
|
||||
"resizeImage",
|
||||
|
||||
@ -31,6 +31,7 @@ export interface AnalysisResult {
|
||||
|
||||
function inferDefaultImageEditSubIntent(text: string): AnalysisResult["subIntent"] {
|
||||
const lowerText = text.toLowerCase();
|
||||
if (/去水印|水印|去logo|去\s*logo|移除logo|去除logo/.test(lowerText)) return "remove_watermark";
|
||||
if (/抠图|去背景|透明背景|去背|扣图|移除背景/.test(lowerText)) return "remove_background";
|
||||
if (/换背景|改背景|背景换成|背景改成|白底|透明底/.test(lowerText)) return "replace_background";
|
||||
if (/扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|比例|画幅|竖版|横版|竖图|横图|9:16|16:9|1:1/.test(lowerText)) return "extend";
|
||||
@ -137,7 +138,7 @@ export function isExplicitImageGenerationRequest(text: string): boolean {
|
||||
|
||||
function isLikelyImageEditRequest(text: string): boolean {
|
||||
const normalizedText = text.toLowerCase();
|
||||
return /抠图|去背景|透明背景|去背|扣图|移除背景|换背景|改背景|背景换成|背景改成|白底|纯色背景|替换.*背景|变清晰|高清|锐化|降噪|提升质量|修复|清晰化|扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|换成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|改成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|比例|画幅|竖版|横版|去除|消除|擦掉|删除|移除|p掉|重绘|风格化|卡通化|动漫风|油画风|转.*风格|变.*风格|改.*风格|调色|调整颜色|亮度|对比度|饱和度|色调|曝光|滤镜|改成.*色|换成.*色|变成.*色|颜色改成|颜色换成|颜色变成|缩放|放大|缩小|调整尺寸|裁剪|resize|crop|修图|p图|改图|调图|编辑.*图|优化.*图|重做|再调整|继续改|继续调/.test(
|
||||
return /抠图|去背景|透明背景|去背|扣图|移除背景|去水印|水印|去logo|去\s*logo|移除logo|去除logo|换背景|改背景|背景换成|背景改成|白底|纯色背景|替换.*背景|变清晰|高清|锐化|降噪|提升质量|修复|清晰化|扩展|拓展|延伸|扩图|outpainting|拓宽|扩大|换成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|改成.*(?:比例|竖版|横版|竖图|横图|9:16|16:9|1:1)|比例|画幅|竖版|横版|去除|消除|擦掉|删除|移除|p掉|重绘|风格化|卡通化|动漫风|油画风|转.*风格|变.*风格|改.*风格|调色|调整颜色|亮度|对比度|饱和度|色调|曝光|滤镜|改成.*色|换成.*色|变成.*色|颜色改成|颜色换成|颜色变成|缩放|放大|缩小|调整尺寸|裁剪|resize|crop|修图|p图|改图|调图|编辑.*图|优化.*图|重做|再调整|继续改|继续调/.test(
|
||||
normalizedText,
|
||||
);
|
||||
}
|
||||
@ -383,6 +384,7 @@ const ANALYZER_SYSTEM_PROMPT = `你是一个友好的AI多模态Agent。用户
|
||||
### image_edit - 图片编辑(用户上传了图片并想编辑)
|
||||
子意图:
|
||||
- remove_background: 抠图、去背景、透明背景
|
||||
- remove_watermark: 去水印、移除图片中的水印或 logo 水印
|
||||
- replace_background: 换背景、改背景、白底
|
||||
- enhance: 变清晰、高清、锐化、降噪
|
||||
- extend: 扩展、拓展、延伸画布
|
||||
@ -766,7 +768,7 @@ async function analyzeWithHardcodedQwen3VlFallback(params: {
|
||||
const prompt = [
|
||||
"你是图片需求分析助手。请结合图片与用户意图,输出严格 JSON,不要输出其他内容。",
|
||||
"intent 只能是 image_edit / vision / image_gen / video_gen / chat。",
|
||||
"subIntent 可选:remove_background / replace_background / enhance / extend / inpaint / style_transfer / color_adjust / redo / resize。",
|
||||
"subIntent 可选:remove_background / remove_watermark / replace_background / enhance / extend / inpaint / style_transfer / color_adjust / redo / resize。",
|
||||
"如果用户提到视频、首帧、尾帧、分镜,intent=video_gen。",
|
||||
"有图片且用户在修改图片时,优先 intent=image_edit。",
|
||||
"JSON 字段:intent, subIntent, confidence, conversationalReply, needsClarification, clarifyingQuestions。",
|
||||
@ -2333,6 +2335,16 @@ export function fallbackKeywordAnalysis(
|
||||
};
|
||||
}
|
||||
|
||||
// 去水印
|
||||
if (/去水印|水印|去logo|去\s*logo|移除logo|去除logo/.test(lowerText)) {
|
||||
return {
|
||||
intent: "image_edit",
|
||||
subIntent: "remove_watermark",
|
||||
confidence: 0.9,
|
||||
conversationalReply: "好的,我来帮你去掉图片里的水印,并保留原图~",
|
||||
};
|
||||
}
|
||||
|
||||
// 换背景
|
||||
if (/换背景|白底|改背景|背景换成|纯色背景|换成.*背景|替换.*背景/.test(lowerText)) {
|
||||
// 提取背景颜色
|
||||
|
||||
@ -224,6 +224,13 @@ function normalizeEditCapability(
|
||||
const normalizedText = String(text || "").toLowerCase();
|
||||
const subIntent = String(analysis.subIntent || "").trim().toLowerCase();
|
||||
|
||||
if (subIntent === "remove_watermark" || /去水印|水印|去logo|去\s*logo|移除logo|去除logo/.test(normalizedText)) {
|
||||
return {
|
||||
capability: "remove_watermark",
|
||||
toolName: "removeWatermark",
|
||||
subIntent: "remove_watermark",
|
||||
};
|
||||
}
|
||||
if (subIntent === "remove_background" || /抠图|去背|去背景|透明底/.test(normalizedText)) {
|
||||
return {
|
||||
capability: "remove_background",
|
||||
|
||||
@ -19,6 +19,7 @@ export type AgentProjectToolName =
|
||||
| "generateImage"
|
||||
| "editImage"
|
||||
| "removeBackground"
|
||||
| "removeWatermark"
|
||||
| "enhanceImage"
|
||||
| "extendImage"
|
||||
| "resizeImage"
|
||||
@ -166,6 +167,14 @@ const INTERNAL_AGENT_TOOLS: AgentProjectToolDefinition[] = [
|
||||
requiresImage: true,
|
||||
producesMedia: true,
|
||||
},
|
||||
{
|
||||
name: "removeWatermark",
|
||||
title: "去水印",
|
||||
description: "清理图片中的水印、Logo 水印或遮挡瑕疵,结果作为新版本保留原图。",
|
||||
category: "image",
|
||||
requiresImage: true,
|
||||
producesMedia: true,
|
||||
},
|
||||
{
|
||||
name: "enhanceImage",
|
||||
title: "清晰增强",
|
||||
|
||||
@ -122,6 +122,11 @@ import {
|
||||
shouldPreserveCanvasAgentSlotOnlyContext,
|
||||
shouldBypassCanvasImagePointsPrecheckForAgentControl,
|
||||
} from "@/lib/canvas/agent-client-intent";
|
||||
import {
|
||||
getDirectAgentToolLabel,
|
||||
getDirectAgentToolSuccessMessage,
|
||||
resolveDirectAgentToolExecution,
|
||||
} from "@/lib/ai/runtime/direct-agent-execution";
|
||||
import {
|
||||
applyCanvasOperationPlanToCanvasData,
|
||||
CanvasAgentMutationError,
|
||||
@ -1015,6 +1020,80 @@ test.describe("canvas chat pure helpers", () => {
|
||||
});
|
||||
});
|
||||
|
||||
test("routes watermark removal through the dedicated direct image tool", () => {
|
||||
const result = resolveDirectAgentToolExecution({
|
||||
mode: "edit_image",
|
||||
routeIntent: "image_edit",
|
||||
routeSubIntent: "remove_watermark",
|
||||
targetSource: "explicit_selection",
|
||||
preferredCapability: "remove_watermark",
|
||||
shouldUseStructuredReply: true,
|
||||
shouldOptimizePrompt: true,
|
||||
shouldApplyImagePipeline: true,
|
||||
shouldApplyVideoPipeline: false,
|
||||
shouldStayConversational: false,
|
||||
shouldPublishToCanvas: false,
|
||||
toolCalls: [
|
||||
{
|
||||
name: "resolveTargetImage",
|
||||
args: { source: "selected_canvas" },
|
||||
},
|
||||
{
|
||||
name: "editTargetImage",
|
||||
reason: "planner only provided the generic edit tool",
|
||||
},
|
||||
],
|
||||
availableTools: ["resolveTargetImage", "editTargetImage", "removeWatermark"],
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
toolName: "removeWatermark",
|
||||
capability: "remove_watermark",
|
||||
sourcePreferences: ["selected_canvas"],
|
||||
});
|
||||
expect(getDirectAgentToolLabel("remove_watermark")).toBe("Agent工具:去水印");
|
||||
expect(getDirectAgentToolSuccessMessage("remove_watermark")).toBe(
|
||||
"已完成去水印处理,结果如下:"
|
||||
);
|
||||
});
|
||||
|
||||
test("plans watermark removal results as non-destructive canvas revisions", () => {
|
||||
const result = buildCanvasAgentDirectWritebackPlan({
|
||||
projectId: plannerContext.projectId || "",
|
||||
chatId: "chat-1",
|
||||
assistantMessageId: "assistant-watermark",
|
||||
operationLabel: "agent-remove_watermark",
|
||||
resultType: "image",
|
||||
resultUrls: ["https://cdn.example.com/watermark-removed.png"],
|
||||
prompt: "把选中图片上的水印去掉",
|
||||
requestTextContent: "把选中图片上的水印去掉,结果放右边",
|
||||
mode: "edit",
|
||||
context: plannerContext,
|
||||
targetRefs: [{ nodeId: "image-1" }],
|
||||
sourceImageUrls: ["https://cdn.example.com/source-watermarked.png"],
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({
|
||||
operation: "append_revision",
|
||||
shouldFillSlot: false,
|
||||
mediaItemIds: ["assistant-watermark:agent-remove_watermark:1"],
|
||||
plan: {
|
||||
operation: "append_revision",
|
||||
anchorNodeId: "image-1",
|
||||
placement: "right",
|
||||
preserveOriginal: true,
|
||||
},
|
||||
});
|
||||
expect(result?.mediaItems[0]).toMatchObject({
|
||||
type: "image",
|
||||
url: "https://cdn.example.com/watermark-removed.png",
|
||||
sourceNodeIds: ["image-1"],
|
||||
metadata: {
|
||||
sourceImageUrls: ["https://cdn.example.com/source-watermarked.png"],
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
test("anchors direct image edits to resolved target refs before fallback selection", () => {
|
||||
const context: CanvasAgentContext = {
|
||||
...plannerContext,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user