import { type ResponseFunctionTool } from "@/services/api/image"; import { skillRuntime } from "@/services/skill-runtime"; import { CREATIVE_AGENT_TOOLS } from "@/lib/creation/creative-agent-tools"; const JSON_RECORD_SCHEMA = { type: "object", additionalProperties: true }; const POSITION_SCHEMA = { type: "object", properties: { x: { type: "number" }, y: { type: "number" } }, required: ["x", "y"], additionalProperties: false }; const VIEWPORT_SCHEMA = { type: "object", properties: { x: { type: "number" }, y: { type: "number" }, k: { type: "number" } }, required: ["x", "y", "k"], additionalProperties: false }; const NODE_TYPE_SCHEMA = { type: "string", enum: ["image", "text", "skill", "video", "audio"] }; const WORKFLOW_NODE_KIND_SCHEMA = { type: "string", enum: ["text", "script", "image", "video", "audio", "character_cards", "character_three_view", "storyboard_video"] }; const GENERATION_MODE_SCHEMA = { type: "string", enum: ["text", "image", "video", "audio"] }; const GENERATION_OPTION_PROPERTIES = { model: { type: "string" }, size: { type: "string" }, quality: { type: "string" }, transparentBackground: { type: "string", enum: ["true", "false"] }, count: { type: "number" }, seconds: { type: "string" }, vquality: { type: "string" }, generateAudio: { type: "string" }, watermark: { type: "string" }, audioVoice: { type: "string" }, audioFormat: { type: "string" }, audioSpeed: { type: "string" }, audioInstructions: { type: "string" }, }; const CANVAS_OP_SCHEMA = { type: "object", properties: { type: { type: "string", enum: ["add_node", "update_node", "delete_node", "delete_connections", "connect_nodes", "set_viewport", "select_nodes", "run_generation"] }, id: { type: "string" }, ids: { type: "array", items: { type: "string" } }, nodeType: NODE_TYPE_SCHEMA, title: { type: "string" }, x: { type: "number" }, y: { type: "number" }, width: { type: "number" }, height: { type: "number" }, position: POSITION_SCHEMA, metadata: JSON_RECORD_SCHEMA, patch: JSON_RECORD_SCHEMA, all: { type: "boolean" }, fromNodeId: { type: "string" }, toNodeId: { type: "string" }, viewport: VIEWPORT_SCHEMA, nodeId: { type: "string" }, mode: GENERATION_MODE_SCHEMA, prompt: { type: "string" }, retry: { type: "boolean" }, }, required: ["type"], additionalProperties: false, }; function toolDefinition(name: string, description: string, properties: Record, required: string[] = [], strict = false): ResponseFunctionTool { return { type: "function", function: { name, description, parameters: { type: "object", properties, required, additionalProperties: false }, strict } }; } function generationToolDefinition(name: string, description: string, mode?: "text" | "image" | "video" | "audio") { return toolDefinition( name, description, { prompt: { type: "string" }, title: { type: "string" }, x: { type: "number" }, y: { type: "number" }, referenceNodeIds: { type: "array", items: { type: "string" } }, ...(mode ? {} : { mode: GENERATION_MODE_SCHEMA }), autoRun: { type: "boolean" }, ...GENERATION_OPTION_PROPERTIES, }, ["prompt"], ); } export const CANVAS_ONLINE_AGENT_TOOLS: ResponseFunctionTool[] = [ ...CREATIVE_AGENT_TOOLS, ...skillRuntime.agentTools("onlineAgent"), toolDefinition("canvas_get_state", "读取当前网页画布的节点、连线、选区和视口。", {}), toolDefinition("canvas_get_context", "读取语义化画布上下文、真实节点 id、连接关系、资源就绪状态和状态哈希。", {}), toolDefinition("canvas_find_nodes", "按标题、内容、提示词、类型、状态或资产检索真实节点。", { query: { type: "string" }, ids: { type: "array", items: { type: "string" } }, types: { type: "array", items: { type: "string" } }, statuses: { type: "array", items: { type: "string" } }, resourceOnly: { type: "boolean" }, limit: { type: "number" } }), toolDefinition("canvas_get_node", "按真实节点 id 精确读取单个节点、资源状态和关联连线。", { id: { type: "string" } }, ["id"]), toolDefinition("canvas_get_connection", "按真实连线 id 精确读取端点节点和 handle 信息。", { id: { type: "string" } }, ["id"]), toolDefinition("canvas_get_generation_tasks", "读取当前画布绑定的生成任务观察状态,不主动轮询上游。", { status: { type: "string" }, nodeIds: { type: "array", items: { type: "string" } }, limit: { type: "number" } }), toolDefinition("canvas_get_resources", "读取画布媒体资源引用、类型、尺寸、大小、时长和就绪状态,不返回媒体 URL。", { nodeIds: { type: "array", items: { type: "string" } }, status: { type: "string" }, limit: { type: "number" } }), toolDefinition("canvas_validate_ops", "在写入前校验节点 id、连接关系和批量操作参数。", { ops: { type: "array", items: CANVAS_OP_SCHEMA } }, ["ops"]), toolDefinition("canvas_get_selection", "读取当前网页画布选中的节点。", {}), toolDefinition("canvas_export_snapshot", "导出当前画布快照,用于理解布局。", {}), toolDefinition( "canvas_apply_ops", "批量操作当前网页画布。复杂写操作应先 canvas_validate_ops;可传 canvas_get_context 返回的 expectedStateHash 防止基于过期状态写入。", { ops: { type: "array", items: CANVAS_OP_SCHEMA }, expectedRevision: { type: "number" }, expectedStateHash: { type: "string" } }, ["ops"], false, ), toolDefinition( "canvas_create_workflow", "创建语义化工作流/流水线:节点使用真实的文本、脚本、图片、视频或音频类型;character_cards=角色拆分图片卡片,character_three_view=角色三视图,storyboard_video=分镜剧情视频。工具会自动生成唯一 id、按节点实际尺寸布局、创建 edges/referenceRefs/referenceNodeIds 连线、选择新节点并复核重叠。媒体节点必须提供有意义的 prompt 或 content;已有素材先 canvas_find_nodes/canvas_get_resources,再把真实 node id 放入 referenceNodeIds。不要用 canvas_create_text_nodes 代替工作流。", { title: { type: "string" }, description: { type: "string" }, nodes: { type: "array", minItems: 1, items: { type: "object", properties: { ref: { type: "string" }, kind: WORKFLOW_NODE_KIND_SCHEMA, title: { type: "string" }, content: { type: "string" }, prompt: { type: "string" }, description: { type: "string" }, referenceRefs: { type: "array", items: { type: "string" } }, referenceNodeIds: { type: "array", items: { type: "string" } }, runGeneration: { type: "boolean" }, width: { type: "number" }, height: { type: "number" }, }, required: ["ref", "kind", "title"], additionalProperties: false, }, }, edges: { type: "array", items: { type: "object", properties: { from: { type: "string" }, to: { type: "string" } }, required: ["from", "to"], additionalProperties: false } }, direction: { type: "string", enum: ["horizontal", "vertical"] }, start: POSITION_SCHEMA, gap: { type: "number" }, autoRun: { type: "boolean" }, }, ["nodes"], ), toolDefinition( "canvas_create_node", "创建任意类型节点:text、image、video、audio。适合创建文本、媒体占位或自定义 metadata 节点。", { nodeType: NODE_TYPE_SCHEMA, title: { type: "string" }, x: { type: "number" }, y: { type: "number" }, width: { type: "number" }, height: { type: "number" }, metadata: JSON_RECORD_SCHEMA }, ["nodeType"], ), toolDefinition("canvas_create_text_node", "在当前画布创建单个文本节点。", { text: { type: "string" }, x: { type: "number" }, y: { type: "number" }, title: { type: "string" }, width: { type: "number" }, height: { type: "number" } }), toolDefinition( "canvas_create_text_nodes", "批量创建文本节点,适合生成标题、段落、脚本、说明等内容块。", { items: { type: "array", minItems: 1, items: { type: "object", properties: { text: { type: "string" }, title: { type: "string" }, x: { type: "number" }, y: { type: "number" }, width: { type: "number" }, height: { type: "number" } }, required: ["text"], additionalProperties: false, }, }, x: { type: "number" }, y: { type: "number" }, gap: { type: "number" }, direction: { type: "string", enum: ["row", "column"] }, }, ["items"], ), toolDefinition("canvas_create_cinematic_session", "把自然语言创作指令提交给后端影视 Agent 会话,后端拆解为剧本、场景、分镜、镜头和成片节点,并返回可写回画布的操作。", { prompt: { type: "string" } }, ["prompt"]), toolDefinition( "canvas_create_image_prompt_flow", "创建提示词文本节点和图片目标节点并自动连线,可选择立即触发生图。", { prompt: { type: "string" }, x: { type: "number" }, y: { type: "number" }, autoRun: { type: "boolean" }, ...GENERATION_OPTION_PROPERTIES }, ["prompt"], ), generationToolDefinition("canvas_create_generation_flow", "创建通用生成流程:提示词文本节点、对应类型的生成目标节点和参考节点连线,可用于文案、生图、视频或音频。"), generationToolDefinition("canvas_generate_text", "创建通用文本生成流程并立即触发生成。", "text"), generationToolDefinition("canvas_generate_image", "创建通用图片生成流程并立即触发生成。", "image"), generationToolDefinition("canvas_generate_video", "创建通用视频生成流程并立即触发生成。", "video"), generationToolDefinition("canvas_generate_audio", "创建通用音频生成流程并立即触发生成。", "audio"), toolDefinition("canvas_update_node", "更新节点基础字段或 metadata。", { id: { type: "string" }, patch: JSON_RECORD_SCHEMA, metadata: JSON_RECORD_SCHEMA }, ["id"]), toolDefinition("canvas_update_node_text", "更新文本节点内容和标题。", { id: { type: "string" }, text: { type: "string" }, title: { type: "string" } }, ["id", "text"]), toolDefinition( "canvas_move_nodes", "移动一个或多个节点,支持绝对坐标或 dx/dy 偏移。", { items: { type: "array", minItems: 1, items: { type: "object", properties: { id: { type: "string" }, x: { type: "number" }, y: { type: "number" }, dx: { type: "number" }, dy: { type: "number" } }, required: ["id"], additionalProperties: false }, }, }, ["items"], ), toolDefinition("canvas_resize_node", "调整节点尺寸。", { id: { type: "string" }, width: { type: "number" }, height: { type: "number" }, freeResize: { type: "boolean" } }, ["id", "width", "height"]), toolDefinition("canvas_delete_nodes", "删除指定节点及相关连线。", { ids: { type: "array", items: { type: "string" }, minItems: 1 } }, ["ids"]), toolDefinition( "canvas_connect_nodes", "批量连接节点。", { connections: { type: "array", minItems: 1, items: { type: "object", properties: { fromNodeId: { type: "string" }, toNodeId: { type: "string" } }, required: ["fromNodeId", "toNodeId"], additionalProperties: false } } }, ["connections"], ), toolDefinition("canvas_select_nodes", "设置当前选中节点。", { ids: { type: "array", items: { type: "string" } } }, ["ids"]), toolDefinition("canvas_set_viewport", "调整画布视口。", { viewport: VIEWPORT_SCHEMA }, ["viewport"]), toolDefinition("canvas_run_generation", "触发指定节点生成;对已有生成任务明确重试时传 retry=true。", { nodeId: { type: "string" }, mode: GENERATION_MODE_SCHEMA, prompt: { type: "string" }, retry: { type: "boolean" } }, ["nodeId"]), ];