import { isZcodeWorkspaceAuthorized, VIDEO_ONLY_AGENT_TOOLBAR_KEYS } from "./authorization"; import { CANVAS_CAPABILITY_REGISTRY } from "@/lib/canvas/capabilities/registry"; import { DEFAULT_CANVAS_TOOLBAR_ITEMS } from "@/lib/canvas-toolbar-config"; import { defaultVideoCanvasFunctionConfig, type VideoCanvasFunctionConfig, } from "@/lib/video-canvas/config"; export type AgentCapabilityAccess = { id: string; workspace: "canvas" | "video"; title: string; authorized: boolean; previouslyExposed: boolean; execution: "server" | "interactive" | "backend_required"; entry: string; note?: string; }; // The full audit manifest is for the report/API. Repeating audit metadata and UI // descriptions in model history can exhaust context before the first edit. export function summarizeAgentCapabilities(items: AgentCapabilityAccess[]) { return items.map(({ id, title, execution, entry, note, authorized }) => ({ id, title, authorized, execution, ...(authorized && execution === "server" ? { entry } : {}), ...(!authorized ? { note: "暂未授权" } : execution === "backend_required" ? { note } : {}), })); } export const VIDEO_CANVAS_EXTRA_ACTIONS = [ ["rename", "节点重命名"], ["move", "节点移动"], ["duplicate", "复制节点"], ["delete", "删除节点"], ["connect", "工作流连线"], ["disconnect", "移除连线"], ["note", "节点批注"], ["text", "编辑文本"], ["create-text", "添加文本节点"], ["arrange", "排列节点"], ["viewport", "画布缩放与定位"], ] as const; export const VIDEO_CANVAS_INTERACTIVE_ACTIONS = [ ["upload-image", "上传图片"], ["upload-video", "上传视频"], ["upload-audio", "上传音频"], ["download", "下载素材"], ["preview", "预览素材"], ["local-edit", "局部编辑"], ["annotate", "标注"], ["video-hd", "视频高清"], ["video-clip", "选择视频剪辑范围"], ["video-crop", "视频裁剪面板"], ["subtitle-erase", "去字幕面板"], ["audio-split", "音视频分离面板"], ["voice-split", "人声分离面板"], ["background-split", "背景音分离面板"], ["director", "导演台"], ["storyboard", "分镜工作台"], ["batch-storyboard", "批量生成分镜"], ["batch-video", "批量生成视频"], ["assets", "素材库"], ["roles", "角色库"], ["styles", "风格库"], ["effects", "特效库"], ["history", "生成历史"], ["workflows", "工作流模板"], ["save", "保存画布"], ["export", "导出画布"], ["import", "导入画布"], ["share", "分享设置"], ["publish", "发布设置"], ["skills", "视频技能"], ["help", "帮助与快捷键"], ["frame-first", "提取首帧"], ["frame-last", "提取尾帧"], ["frame-current", "提取指定时间帧"], ] as const; export const IMAGE_CANVAS_OPERATIONS = [ "create_agent_slot", "create_text_node", "fill_slot", "insert_beside", "append_revision", "replace_node_media", "add_annotation", "link_nodes", "move_nodes", "delete_nodes", "rename_node", "update_note", "update_text", ] as const; export function isExplicitDestructiveIntent(text: string) { return ( /删除|移除|清空|覆盖|替换原图/.test(text) && !/(?:不要|不许|禁止|别|不需要).{0,12}(?:删除|移除|清空|覆盖)/.test(text) ); } const imageOperationTitles: Record = { create_agent_slot: "创建输出槽位", create_text_node: "创建文本节点", fill_slot: "填充输出槽位", insert_beside: "在素材旁添加结果", append_revision: "追加素材版本", replace_node_media: "替换节点媒体", add_annotation: "添加标注", link_nodes: "节点连线", move_nodes: "移动节点", delete_nodes: "删除节点", rename_node: "重命名节点", update_note: "更新批注", update_text: "更新文本", }; export function getCanvasAgentAccessManifest( videoConfig: VideoCanvasFunctionConfig = defaultVideoCanvasFunctionConfig, ): AgentCapabilityAccess[] { return [ ...CANVAS_CAPABILITY_REGISTRY.map( (capability): AgentCapabilityAccess => ({ id: capability.id, workspace: "canvas", title: capability.title, authorized: true, previouslyExposed: !["image.add_to_chat", "image.layout_replace", "image.download"].includes( capability.id, ) && capability.agent.exposed && capability.executionMode !== "local" && !capability.id.includes("3d") && capability.risk !== "destructive", execution: capability.executionMode === "interactive" || capability.executionMode === "local" || [ "image.text_edit", "image.local_edit", "image.scale_adjust", "image.crop", "image.flip_rotate", ].includes(capability.id) ? "interactive" : "server", entry: capability.agent.toolName || capability.id.replaceAll(".", "_"), note: capability.risk === "destructive" ? "需要用户明确要求及明确目标;模型不能自行确认" : capability.executionMode === "hybrid" ? "参数齐全时执行,否则打开真实交互面板" : undefined, }), ), ...DEFAULT_CANVAS_TOOLBAR_ITEMS.map( (item): AgentCapabilityAccess => ({ id: `canvas.ui.${item.key}`, workspace: VIDEO_ONLY_AGENT_TOOLBAR_KEYS.has(item.key) ? "video" : "canvas", title: `${item.group} · ${item.label}`, authorized: true, previouslyExposed: false, execution: "interactive", entry: "openCanvasFeature", note: "操作当前可见的真实入口;隐藏入口保持隐藏,文件选择、支付、登录、发布和发送消息由用户完成", }), ), ...IMAGE_CANVAS_OPERATIONS.map( (operation): AgentCapabilityAccess => ({ id: `canvas.operation.${operation}`, workspace: "canvas", title: `画布操作 · ${imageOperationTitles[operation] || operation}`, authorized: true, previouslyExposed: false, execution: "server", entry: "editCanvasNodes", }), ), ...Object.values(videoConfig.functions).map( (definition): AgentCapabilityAccess => ({ id: `video.function.${definition.key}`, workspace: "video", title: definition.label, authorized: true, previouslyExposed: [ "story-script", "video-analysis", "image-to-prompt", "text-to-video", "first-frame-video", "first-last-frame-video", ].includes(definition.key), execution: definition.key === "audio-to-video" ? "backend_required" : ["local", "pick-object"].includes(definition.route) ? "interactive" : "server", entry: "runVideoCanvasFunction", note: definition.key === "audio-to-video" ? "当前页面未接真实音频驱动视频后端,已授权入口但不能伪称完成音频驱动" : !definition.enabled ? "已授权;管理员关闭了底层功能,需启用对应服务后才能执行" : undefined, }), ), ...VIDEO_CANVAS_EXTRA_ACTIONS.map( ([id, title]): AgentCapabilityAccess => ({ id: `video.node.${id}`, workspace: "video", title, authorized: true, previouslyExposed: false, execution: "server", entry: "editVideoCanvas", }), ), ...( [ ["extract-frame", "真实视频截帧"], ["trim", "真实视频剪辑导出"], ["crop", "真实视频裁剪"], ["extract-audio", "提取完整音轨"], ["mute", "生成无声视频"], ] as const ).map( ([id, title]): AgentCapabilityAccess => ({ id: `video.media.${id}`, workspace: "video", title, authorized: true, previouslyExposed: false, execution: "server", entry: "processVideoMedia", note: "使用真实媒体处理并上传现有存储,不复用页面的模拟产物;单次视频不超过120秒", }), ), ...VIDEO_CANVAS_INTERACTIVE_ACTIONS.map( ([id, title]): AgentCapabilityAccess => ({ id: `video.ui.${id}`, workspace: "video", title, authorized: true, previouslyExposed: false, execution: ["video-hd", "subtitle-erase", "voice-split", "background-split"].includes(id) ? "backend_required" : "interactive", entry: "openVideoCanvasFeature", note: [ "video-crop", "video-hd", "subtitle-erase", "audio-split", "voice-split", "background-split", "frame-first", "frame-last", "frame-current", ].includes(id) ? "页面当前为占位/模拟流程;只授权设置入口,不执行模拟产物或声称媒体已处理" : undefined, }), ), ].map(item => ({ ...item, authorized: isZcodeWorkspaceAuthorized(item.workspace), ...(!isZcodeWorkspaceAuthorized(item.workspace) ? { note: ["用户暂未授权视频画布能力", item.note].filter(Boolean).join(";") } : {}) })); }