fix(*): 创作工作台 - 修复 Agent、资源引用、附件交互与 Agnes 视频协议

This commit is contained in:
ddCat
2026-08-27 22:12:04 +08:00
parent 0e33cc805e
commit 4675cf4c99
33 changed files with 1218 additions and 239 deletions

View File

@@ -236,7 +236,7 @@ export function attachNodeToStoryboardRow(nodes: CanvasNodeData[], connection: P
if (!scriptNodeId || !linkedNode || !scriptNode) return nodes;
const row = rowId ? scriptNode.metadata?.storyboard?.rows.find((item) => item.id === rowId) : undefined;
const videoPrompt = row ? (row.videoMotionPrompt || row.plotDescription).trim() : "";
const videoComposerContent = row ? storyboardComposerContent(videoPrompt, storyboardRowReferenceNodeIds(scriptNode, row, nodes, [], false)) : "";
const videoComposerContent = row ? storyboardComposerContent(videoPrompt, storyboardRowReferenceNodeIds(scriptNode, row, nodes, [], false), nodes) : "";
return nodes.map((node) => {
if (row && node.id === linkedNode.id && scriptNodeId === connection.fromNodeId && node.type === CanvasNodeType.Video) {
@@ -272,7 +272,8 @@ export function expandStoryboardTextMentions(prompt: string, references: CanvasR
let expanded = prompt;
references.filter((reference) => reference.active && reference.kind === "text" && reference.text?.trim()).forEach((reference) => {
const replacement = `【项目设定:${reference.title}】\n${reference.text!.trim()}`;
for (const token of [canvasResourceMentionToken(reference), `@${reference.label}`]) {
for (const token of [canvasResourceMentionToken(reference), `@${reference.label}`, reference.nodeId ? `@[node:${reference.nodeId}]` : ""]) {
if (!token) continue;
if (expanded.includes(token)) expanded = expanded.split(token).join(replacement);
}
});

View File

@@ -21,23 +21,21 @@ export type CanvasResourceReference = {
skill?: Skill;
assetId?: string;
category?: AssetCategory;
mentionToken?: string;
};
export function canvasResourceMentionToken(reference: CanvasResourceReference) {
if (reference.mentionToken) return reference.mentionToken;
if (reference.kind === "skill" && reference.skill?.skill_id) return `@[skill:${reference.skill.skill_id}]`;
if (reference.assetId) return `@[asset:${reference.assetId}]`;
return `@[node:${reference.nodeId}]`;
return `@${reference.label}`;
}
export function removeCanvasResourceMention(prompt: string, reference: CanvasResourceReference) {
const token = canvasResourceMentionToken(reference);
if (!token || !prompt.includes(token)) return prompt;
return prompt
.split(token)
.join("")
.replace(/[ \t]{2,}/g, " ")
.replace(/\n{3,}/g, "\n\n")
.trim();
export function normalizeCanvasNodeMentionTokens(prompt: string, references: CanvasResourceReference[]) {
return references.reduce((value, reference) => {
if (!reference.nodeId || reference.assetId || reference.kind === "skill") return value;
return value.split(`@[node:${reference.nodeId}]`).join(`@${reference.label}`);
}, prompt);
}
export function buildAssetMentionReferences(assets: Asset[]): CanvasResourceReference[] {
@@ -73,6 +71,10 @@ export function buildNodeMentionReferences(node: CanvasNodeData, nodes: CanvasNo
return labelResourceNodes(getMentionResourceNodes(node.id, nodes, connections), true);
}
export function buildOrderedCanvasResourceReferences(nodes: CanvasNodeData[], active = true) {
return labelResourceNodes(nodes.filter(isResourceNode), active);
}
export function getMentionResourceNodes(nodeId: string, nodes: CanvasNodeData[], connections: CanvasConnection[]) {
const configInputs = getConnectedConfigResourceNodes(nodeId, nodes, connections);
if (configInputs.length) return configInputs;
@@ -138,7 +140,7 @@ function labelResourceNodes(nodes: CanvasNodeData[], active: boolean) {
kind,
label,
title: node.title || label,
previewUrl: node.metadata?.workflowKind === "character" ? node.metadata.characterCoverUrl : node.type === CanvasNodeType.Drawing ? node.metadata?.drawingPreviewUrl : node.metadata?.content,
previewUrl: node.metadata?.workflowKind === "character" ? node.metadata.characterCoverUrl : node.type === CanvasNodeType.Drawing ? node.metadata?.drawingPreviewUrl : node.metadata?.previewContent || node.metadata?.content,
storageKey: node.metadata?.storageKey,
text: node.metadata?.workflowKind === "character" ? node.metadata.characterPrompt : node.type === CanvasNodeType.Text ? node.metadata?.content || node.metadata?.prompt : node.type === CanvasNodeType.Skill ? skillResourceText(node) : undefined,
active,

View File

@@ -1,6 +1,7 @@
import { nanoid } from "nanoid";
import { storyboardAssetRoleForNode } from "@/lib/canvas/canvas-storyboard-assets";
import { buildOrderedCanvasResourceReferences, canvasResourceMentionToken } from "@/lib/canvas/canvas-resource-references";
import { CanvasNodeType, type CanvasConnection, type CanvasNodeData, type StoryboardAssetBinding, type StoryboardRow } from "@/types/canvas";
export function storyboardRowReferenceNodeIds(
@@ -28,8 +29,13 @@ export function storyboardRowReferenceNodeIds(
return Array.from(referenceIds).filter((nodeId) => nodes.some((node) => node.id === nodeId));
}
export function storyboardComposerContent(prompt: string, referenceNodeIds: string[]) {
const mentions = Array.from(new Set(referenceNodeIds)).map((nodeId) => `@[node:${nodeId}]`);
export function storyboardComposerContent(prompt: string, referenceNodeIds: string[], nodes: CanvasNodeData[]) {
const referenceIds = Array.from(new Set(referenceNodeIds));
const referenceNodes = referenceIds.flatMap((nodeId) => {
const node = nodes.find((candidate) => candidate.id === nodeId);
return node ? [node] : [];
});
const mentions = buildOrderedCanvasResourceReferences(referenceNodes).map(canvasResourceMentionToken);
return mentions.length ? [`参考资产:${mentions.join(" ")}`, prompt.trim()].filter(Boolean).join("\n") : prompt.trim();
}