import { z } from "zod"; import type { CanvasCapabilityClientAction, CanvasCapabilityDefinition, CanvasCapabilityId, CanvasCapabilityManifestEntry, SelectedImageToolbarActionKey, } from "./types"; const emptyArgsSchema = z.object({}).passthrough(); const promptArgsSchema = z .object({ prompt: z.string().trim().min(1).max(8_000).optional(), }) .passthrough(); const resizeArgsSchema = z .object({ width: z.number().int().positive().max(16_384).optional(), height: z.number().int().positive().max(16_384).optional(), aspectRatio: z.string().trim().max(32).optional(), }) .passthrough(); const extendArgsSchema = z .object({ prompt: z.string().trim().min(1).max(8_000).optional(), xScale: z.number().min(1.1).max(4).optional(), yScale: z.number().min(1.1).max(4).optional(), }) .passthrough(); const angleArgsSchema = z .object({ horizontalAngle: z.number().min(0).max(360).optional(), verticalAngle: z.number().min(-30).max(90).optional(), zoom: z.number().min(0).max(10).optional(), }) .passthrough(); const cropArgsSchema = z .object({ x: z.number().min(0).optional(), y: z.number().min(0).optional(), width: z.number().positive().optional(), height: z.number().positive().optional(), }) .passthrough(); const transformArgsSchema = z .object({ rotate: z.number().min(-360).max(360).optional(), flipHorizontal: z.boolean().optional(), flipVertical: z.boolean().optional(), }) .passthrough(); type DefinitionInput = Omit< CanvasCapabilityDefinition, "selection" | "requiresRemoteImage" | "confirmation" | "agent" | "mcp" > & { selection?: Partial; requiresRemoteImage?: boolean; confirmation?: CanvasCapabilityDefinition["confirmation"]; agent?: Partial; mcp?: Partial; }; function defineCapability(input: DefinitionInput): CanvasCapabilityDefinition { const mcpToolName = input.id.replaceAll(".", "_"); return { ...input, requiresRemoteImage: input.requiresRemoteImage ?? true, selection: { nodeTypes: ["image"], min: input.selection?.min ?? 1, ...(input.selection?.max ? { max: input.selection.max } : {}), }, confirmation: input.confirmation ?? "never", agent: { exposed: input.agent?.exposed ?? true, aliases: input.agent?.aliases ?? [], toolName: input.agent?.toolName ?? mcpToolName, }, mcp: { exposed: input.mcp?.exposed ?? true, toolName: input.mcp?.toolName ?? mcpToolName, }, }; } export const CANVAS_CAPABILITY_REGISTRY = [ defineCapability({ id: "image.add_to_chat", title: "添加到对话", description: "将选中图片加入当前 Agent 对话上下文。", clientAction: "add-to-chat", toolbarSettingKey: "imageAddToChat", executionMode: "local", risk: "read", modelPolicy: "none", requiresRemoteImage: false, inputSchema: emptyArgsSchema, agent: { exposed: false }, mcp: { exposed: false }, }), defineCapability({ id: "image.pick_object", title: "识物", description: "进入图片点选识物模式,并把识别结果加入对话上下文。", clientAction: "pick-object", toolbarActionKey: "pickObject", toolbarSettingKey: "imagePickObject", executionMode: "interactive", risk: "read", modelPolicy: "feature-setting", confirmation: "interactive", inputSchema: z .object({ x: z.number().min(0).max(1).optional(), y: z.number().min(0).max(1).optional() }) .passthrough(), agent: { aliases: ["识物", "识别物品", "选择物体"] }, }), defineCapability({ id: "image.enhance", title: "高清增强", description: "使用系统配置的增强服务提升图片清晰度。", clientAction: "enhance", toolbarActionKey: "enhance", toolbarSettingKey: "imageEnhance", executionMode: "headless", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.imageEnhance", inputSchema: z.object({ scaleFactor: z.number().min(1).max(8).optional() }).passthrough(), agent: { toolName: "enhanceImage", aliases: ["高清", "增强", "变清晰"] }, }), defineCapability({ id: "image.remove_background", title: "抠图去背", description: "调用系统抠图能力移除图片背景。", clientAction: "rmbg", toolbarActionKey: "removeBackground", toolbarSettingKey: "imageRemoveBackground", executionMode: "headless", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.removeBackground", inputSchema: promptArgsSchema, agent: { toolName: "removeBackground", aliases: ["抠图", "去背景", "透明背景"] }, }), defineCapability({ id: "image.ai_wash", title: "AI洗图", description: "按管理员配置的预设、档位和模型执行 AI 洗图。", clientAction: "ai-wash", toolbarActionKey: "aiWashQuick", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.aiWash", confirmation: "interactive", inputSchema: z .object({ prompt: z.string().trim().min(1).max(8_000).optional(), presetId: z.string().trim().min(1).optional(), modelId: z.string().trim().min(1).optional(), levels: z.record(z.number().int().nonnegative()).optional(), }) .passthrough(), agent: { aliases: ["洗图", "AI洗图", "重新洗图"] }, }), defineCapability({ id: "image.text_edit", title: "图片改字", description: "识别图片文字并打开可编辑文字面板。", clientAction: "text-edit", toolbarActionKey: "textEdit", toolbarSettingKey: "imageTextEdit", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.textEdit", confirmation: "interactive", inputSchema: promptArgsSchema, agent: { aliases: ["改字", "修改图片文字", "替换文案"] }, }), defineCapability({ id: "image.box_cutout", title: "框选抠图", description: "框选图片区域后提取指定主体。", clientAction: "box-cutout", toolbarActionKey: "boxCutout", toolbarSettingKey: "imageBoxCutout", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", confirmation: "interactive", inputSchema: cropArgsSchema, agent: { toolName: "boxCutout", aliases: ["框选抠图", "抠出这部分"] }, }), defineCapability({ id: "image.local_edit", title: "局部编辑", description: "按框选区域与区域提示词执行局部重绘。", clientAction: "local-edit", toolbarActionKey: "localEdit", toolbarSettingKey: "imageLocalEdit", executionMode: "hybrid", risk: "external", modelPolicy: "agent-selected", confirmation: "interactive", inputSchema: promptArgsSchema, agent: { toolName: "localEditImage", aliases: ["局部编辑", "局部重绘"] }, }), defineCapability({ id: "image.layout_replace", title: "排版替换", description: "参考详情图的排版与尺寸比例生成新的 AI 图片结果。", clientAction: "layout-replace", toolbarActionKey: "layoutReplace", toolbarSettingKey: "imageLayoutReplace", executionMode: "interactive", risk: "external", modelPolicy: "feature-setting", confirmation: "interactive", inputSchema: emptyArgsSchema, agent: { exposed: false }, mcp: { exposed: false }, }), defineCapability({ id: "image.scale_adjust", title: "比例调整", description: "按目标框等比缩放和移动选中主体。", clientAction: "scale-adjust", toolbarSettingKey: "imageLocalEdit", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", confirmation: "interactive", inputSchema: cropArgsSchema, agent: { aliases: ["比例调整", "缩放主体", "调整主体位置"] }, }), defineCapability({ id: "image.remove_watermark", title: "去水印", description: "使用系统配置的服务移除水印和画面瑕疵。", clientAction: "watermark", toolbarActionKey: "removeWatermark", toolbarSettingKey: "imageRemoveWatermark", executionMode: "headless", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.removeWatermark", inputSchema: promptArgsSchema, agent: { toolName: "removeWatermark", aliases: ["去水印", "去印", "清理水印"] }, }), defineCapability({ id: "image.resize", title: "尺寸调整", description: "调整图片尺寸、比例和主体位置。", clientAction: "resize", toolbarActionKey: "resize", toolbarSettingKey: "imageResize", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", confirmation: "interactive", inputSchema: resizeArgsSchema, agent: { toolName: "resizeImage", aliases: ["调整尺寸", "改比例", "改分辨率"] }, }), defineCapability({ id: "image.multi_angle", title: "多视角", description: "按水平角、俯仰角和景别生成主体新视角。", clientAction: "angle", toolbarActionKey: "multiAngle", toolbarSettingKey: "imageMultiAngle", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", confirmation: "interactive", inputSchema: angleArgsSchema, agent: { toolName: "angleEditImage", aliases: ["多视角", "换角度", "旋转视角"] }, }), defineCapability({ id: "image.generate_3d_model", title: "生成3D模型", description: "使用系统配置的 Tripo 模型从图片生成 3D 模型。", clientAction: "generate-3d-model", toolbarActionKey: "generate3dModel", toolbarSettingKey: "imageGenerate3dModel", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.tripo3d", confirmation: "interactive", inputSchema: z .object({ modelId: z.string().trim().min(1).optional(), prompt: z.string().trim().min(1).max(8_000).optional(), }) .passthrough(), agent: { aliases: ["生成3D模型", "转成3D模型", "Tripo"] }, }), defineCapability({ id: "image.generate_3d_world", title: "生成3D世界", description: "使用系统配置的 World Labs 模型生成可漫游 3D 世界。", clientAction: "generate-3d-world", toolbarActionKey: "generate3dWorld", toolbarSettingKey: "imageGenerate3dWorld", executionMode: "hybrid", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.worldLabs3d", confirmation: "interactive", inputSchema: z .object({ modelId: z.string().trim().min(1).optional(), prompt: z.string().trim().min(1).max(8_000).optional(), }) .passthrough(), agent: { aliases: ["生成3D世界", "生成场景", "World Labs"] }, }), defineCapability({ id: "image.layer_split", title: "图层拆分", description: "将图片拆分为可独立编辑的图层节点。", clientAction: "layer-split", toolbarActionKey: "layerSplit", toolbarSettingKey: "imageLayerSplit", executionMode: "headless", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.layerSplit", inputSchema: emptyArgsSchema, agent: { aliases: ["图层拆分", "拆图层", "分层"] }, }), defineCapability({ id: "image.extend", title: "扩图", description: "向指定方向扩展画面并补全内容。", clientAction: "extend", toolbarActionKey: "extend", toolbarSettingKey: "imageExtend", executionMode: "headless", risk: "external", modelPolicy: "feature-setting", modelSettingKey: "canvas.extend", inputSchema: extendArgsSchema, agent: { toolName: "extendImage", aliases: ["扩图", "补边", "扩展画面"] }, }), defineCapability({ id: "image.crop", title: "裁剪", description: "打开裁剪面板,或按完整坐标直接裁剪。", clientAction: "crop", toolbarActionKey: "crop", toolbarSettingKey: "imageCrop", executionMode: "hybrid", risk: "write", modelPolicy: "none", requiresRemoteImage: false, confirmation: "interactive", inputSchema: cropArgsSchema, agent: { aliases: ["裁剪", "剪裁", "截取画面"] }, }), defineCapability({ id: "image.adjust", title: "画面调整", description: "打开亮度、对比度、饱和度等图片调整面板。", clientAction: "adjust", toolbarActionKey: "adjust", toolbarSettingKey: "imageAdjust", executionMode: "interactive", risk: "write", modelPolicy: "none", requiresRemoteImage: false, confirmation: "interactive", inputSchema: z.record(z.number()).optional().default({}), agent: { aliases: ["调色", "调整亮度", "调整对比度"] }, }), defineCapability({ id: "image.flip_rotate", title: "翻转与旋转", description: "翻转或旋转选中图片。", clientAction: "flip-rotate", toolbarActionKey: "flipRotate", toolbarSettingKey: "imageFlipRotate", executionMode: "hybrid", risk: "write", modelPolicy: "none", requiresRemoteImage: false, confirmation: "interactive", inputSchema: transformArgsSchema, agent: { aliases: ["翻转", "旋转图片", "镜像"] }, }), defineCapability({ id: "image.prompt_regenerate", title: "提示词重绘", description: "按新的提示词和系统生图模型重绘选中图片。", clientAction: "prompt-regenerate", toolbarActionKey: "promptRegenerate", toolbarSettingKey: "imagePromptRegenerate", executionMode: "hybrid", risk: "external", modelPolicy: "agent-selected", confirmation: "interactive", inputSchema: promptArgsSchema, agent: { toolName: "editTargetImage", aliases: ["重绘", "按提示词重做"] }, }), defineCapability({ id: "image.note", title: "添加批注", description: "给图片添加可作为 Agent 上下文的批注。", clientAction: "note", toolbarActionKey: "note", toolbarSettingKey: "imageNote", executionMode: "hybrid", risk: "write", modelPolicy: "none", requiresRemoteImage: false, confirmation: "interactive", inputSchema: z.object({ text: z.string().trim().max(1_000).optional() }).passthrough(), agent: { aliases: ["添加批注", "备注", "标注"] }, }), defineCapability({ id: "image.rename", title: "重命名", description: "修改选中图片节点标题。", clientAction: "rename", toolbarSettingKey: "imageRename", executionMode: "hybrid", risk: "write", modelPolicy: "none", requiresRemoteImage: false, inputSchema: z.object({ title: z.string().trim().min(1).max(120).optional() }).passthrough(), agent: { aliases: ["重命名", "改名", "修改标题"] }, }), defineCapability({ id: "image.download", title: "下载图片", description: "下载选中图片资源。", clientAction: "download", toolbarSettingKey: "imageDownload", executionMode: "local", risk: "read", modelPolicy: "none", requiresRemoteImage: false, inputSchema: emptyArgsSchema, agent: { exposed: false }, mcp: { exposed: false }, }), defineCapability({ id: "image.delete", title: "删除图片", description: "从当前画布删除选中图片节点。", clientAction: "delete", toolbarSettingKey: "imageDelete", executionMode: "local", risk: "destructive", modelPolicy: "none", requiresRemoteImage: false, confirmation: "always", inputSchema: z.object({ confirmed: z.literal(true).optional() }).passthrough(), agent: { aliases: ["删除图片", "移除图片"] }, }), ] as const satisfies readonly CanvasCapabilityDefinition[]; const capabilityById = new Map( CANVAS_CAPABILITY_REGISTRY.map((capability) => [capability.id, capability]), ); const capabilityByClientAction = new Map( CANVAS_CAPABILITY_REGISTRY.map((capability) => [capability.clientAction, capability]), ); const capabilityByToolbarAction = new Map< SelectedImageToolbarActionKey, CanvasCapabilityDefinition >( CANVAS_CAPABILITY_REGISTRY.flatMap((capability) => capability.toolbarActionKey ? [[capability.toolbarActionKey, capability]] : [], ), ); export function getCanvasCapability(id: CanvasCapabilityId) { return capabilityById.get(id) ?? null; } export function getCanvasCapabilityByClientAction(action: CanvasCapabilityClientAction) { return capabilityByClientAction.get(action) ?? null; } export function getCanvasCapabilityByToolbarAction(action: SelectedImageToolbarActionKey) { return capabilityByToolbarAction.get(action) ?? null; } export function parseCanvasCapabilityArgs(id: CanvasCapabilityId, value: unknown) { const capability = getCanvasCapability(id); if (!capability) throw new Error(`Unknown canvas capability: ${id}`); return capability.inputSchema.parse(value ?? {}); } export function getCanvasCapabilityManifest(): CanvasCapabilityManifestEntry[] { return CANVAS_CAPABILITY_REGISTRY.map(({ inputSchema: _inputSchema, ...capability }) => capability); }