fix(canvas): 媒体提示词 - 统一 Agent 更新与画布生成读取生成合同
This commit is contained in:
@@ -11,7 +11,7 @@ import { normalizeVideoDuration, normalizeVideoResolution } from "@/lib/video-ge
|
||||
import { defaultModelCapabilityConfig, modelCapabilityConfigFor, normalizeImageValue, normalizeVideoValue, workflowFieldChoiceValues, workflowFieldCurrentValue, workflowFieldKey, workflowFieldNumberBounds, workflowFieldRandomKey, workflowFieldSubmissionValue, workflowFieldValueError, workflowImageCapabilityConfig, workflowOutputSizeValue, workflowParameterFields, workflowVideoCapabilityConfig, workflowVideoFieldsFromJson, type WorkflowVideoFieldLike } from "@/lib/model-capabilities";
|
||||
import { defaultImageParamsForModel, modelCompatibilityError, modelRequestOptions, resolveCompatibleModel, resolveModelGenerationDefaults, type ModelRequirements } from "@/lib/model-selection";
|
||||
import { resolveCanvasWorkflowProvider } from "@/lib/canvas/canvas-workflow";
|
||||
import { canonicalGenerationMetadata } from "@/lib/canvas/generation-contract";
|
||||
import { canonicalGenerationMetadata, nodeGenerationPrompt } from "@/lib/canvas/generation-contract";
|
||||
import type { CanvasAudioSettingKey } from "./canvas-audio-settings-popover";
|
||||
import { useActiveTheme } from "@/stores/canvas/use-canvas-theme-store";
|
||||
import { workflowProviderPluginEnabled } from "@/lib/plugins/builtin/workflows";
|
||||
@@ -145,7 +145,7 @@ export function CanvasConfigNodePanel({ node, isRunning, inputSummary, onConfigC
|
||||
];
|
||||
const chipStyle = { background: theme.node.fill, color: theme.node.text };
|
||||
const hasAnyInput = Boolean(inputSummary.textCount || inputSummary.imageCount || inputSummary.videoCount || inputSummary.audioCount || inputSummary.characterCount);
|
||||
const hasComposerContent = Boolean((node.metadata?.composerContent ?? node.metadata?.prompt ?? "").trim());
|
||||
const hasComposerContent = Boolean(nodeGenerationPrompt(node).trim());
|
||||
const workflowParameterError = firstWorkflowParameterError(dynamicWorkflowFields, node.metadata?.workflowParameters || {});
|
||||
const capabilityError = workflowParameterError || (workflowProvider === "runninghub"
|
||||
? (!workflowProviderPluginEnabled(runtimeStatuses, "runninghub") ? "RunningHub 工作流插件未启用" : !globalConfig.runningHub.enabled ? "请先在设置中启用 RunningHub" : !node.metadata?.runningHubWorkflowId ? `请选择${capabilityLabel(workflowCapability)}工作流或 App` : !selectedRunningHubWorkflow ? "当前画布引用的 RunningHub 条目已不存在,请重新选择" : selectedRunningHubCapability !== workflowCapability ? `当前条目用途为${capabilityLabel(selectedRunningHubCapability || "image")},请切换画布模式或重新选择条目` : undefined)
|
||||
|
||||
@@ -9,11 +9,12 @@ import { canvasNodeVideoPreviewUrl, canvasVideoAssetPreviewUrl } from "@/lib/can
|
||||
import { isNeutralColorGrade, resolveCanvasColorGradeReference } from "@/lib/canvas/canvas-color-grade";
|
||||
import { getNodeGenerationMode, getNodeResourceKind } from "@/lib/canvas/node-registry";
|
||||
import { mediaConversionSourceFingerprint } from "@/lib/media-conversion/contracts";
|
||||
import { audioFileExtension } from "@/lib/character-voice-formats";
|
||||
import { resolveCanvasDrawingReference } from "@/lib/canvas/canvas-drawing-reference";
|
||||
import { compileCharacterReferencePrompt, normalizeCharacterImageMentions } from "@/lib/canvas/canvas-character-reference";
|
||||
import { nodeReferenceImage } from "@/lib/canvas/canvas-project-generation";
|
||||
import { isCanvasWorkflowProvider } from "@/lib/canvas/canvas-workflow";
|
||||
import { audioFileExtension } from "@/lib/character-voice-formats";
|
||||
import { nodeGenerationPrompt } from "@/lib/canvas/generation-contract";
|
||||
import type { ModelReferenceLimits } from "@/lib/model-selection";
|
||||
import type { Asset } from "@/stores/use-asset-store";
|
||||
|
||||
@@ -89,7 +90,7 @@ export function buildNodeGenerationContext(nodeId: string, nodes: CanvasNodeData
|
||||
const hasConnectedMedia = connectedInputs.some((input) => input.type === "image" || input.type === "video" || input.type === "audio" || input.type === "character");
|
||||
// 豆包音频按连线决定纯文本、参考音频或参考图片,不能因为提示词里没有逐个 @ 就丢掉已连接素材。
|
||||
const includeConnectedAudioMedia = Boolean(sourceNode && getNodeGenerationMode(sourceNode) === "audio");
|
||||
if ((promptOnly && hasConnectedMedia) || (Boolean(sourceNode?.metadata?.composerContent?.trim()) && (sourceNode?.type === CanvasNodeType.Config || isWorkflowSource)) || hasExplicitResourceMention) {
|
||||
if ((promptOnly && hasConnectedMedia) || (sourceNode ? Boolean(nodeGenerationPrompt(sourceNode).trim()) && (sourceNode.type === CanvasNodeType.Config || isWorkflowSource) : false) || hasExplicitResourceMention) {
|
||||
const autoIncludeWorkflowMedia = isWorkflowSource || includeConnectedAudioMedia;
|
||||
return buildComposerGenerationContext(
|
||||
mentionInputs,
|
||||
@@ -582,7 +583,7 @@ export async function hydrateNodeGenerationContext(context: NodeGenerationContex
|
||||
function readNodeTextInput(node: CanvasNodeData) {
|
||||
if (node.type === CanvasNodeType.Text) return node.metadata?.content || node.metadata?.prompt || "";
|
||||
if (node.type === CanvasNodeType.Skill) return readSkillInput(node);
|
||||
return node.metadata?.prompt || "";
|
||||
return nodeGenerationPrompt(node);
|
||||
}
|
||||
|
||||
function readCharacterReference(node: CanvasNodeData): CharacterGenerationReference | null {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { ArrowUp, ChevronDown, FileText, ImagePlus, LayoutList, LoaderCircle, Ma
|
||||
|
||||
import { ModelPicker } from "@/components/model-picker";
|
||||
import { modelOptionName, resolveModelChannel, useEffectiveConfig } from "@/stores/use-config-store";
|
||||
import { canonicalGenerationMetadata } from "@/lib/canvas/generation-contract";
|
||||
import { canonicalGenerationMetadata, nodeGenerationPrompt } from "@/lib/canvas/generation-contract";
|
||||
import { PROMPT_EDITOR_VIEWPORT_MARGIN } from "@/lib/canvas/canvas-prompt-editor-size";
|
||||
import { CreditSymbol, requestCreditCost } from "@/constant/credits";
|
||||
import { canvasThemes } from "@/lib/canvas-theme";
|
||||
@@ -91,7 +91,7 @@ export function CanvasNodePromptPanel({ projectId, node, isRunning, onPromptChan
|
||||
node = { ...node, metadata: canonicalGenerationMetadata(node, mode) };
|
||||
const hasTextContent = node.type === CanvasNodeType.Text && Boolean(node.metadata?.content?.trim());
|
||||
const hasImageContent = node.type === CanvasNodeType.Image && Boolean(node.metadata?.content);
|
||||
const savedPrompt = node.metadata?.composerContent ?? node.metadata?.prompt ?? "";
|
||||
const savedPrompt = nodeGenerationPrompt(node);
|
||||
const [prompt, setPrompt] = useState(savedPrompt);
|
||||
const promptRef = useRef(savedPrompt);
|
||||
const [presetOpen, setPresetOpen] = useState(false);
|
||||
|
||||
@@ -14,6 +14,7 @@ import { formatBytes, getDataUrlByteSize } from "@/lib/image-utils";
|
||||
import { generationErrorMessage } from "@/lib/generation-error";
|
||||
import { useCopyText } from "@/hooks/use-copy-text";
|
||||
import { producedModelLabel } from "@/lib/canvas/produced-model";
|
||||
import { nodeGenerationPrompt } from "@/lib/canvas/generation-contract";
|
||||
import { useActiveTheme } from "@/stores/canvas/use-canvas-theme-store";
|
||||
import { useEffectiveConfig } from "@/stores/use-config-store";
|
||||
import { CanvasNodeType, type CanvasNodeData, type CanvasNodeMetadata, type CanvasWorkspaceMode, type ViewportTransform } from "@/types/canvas";
|
||||
@@ -226,7 +227,7 @@ export function CanvasNodeToolbar({
|
||||
const isAudio = node.type === CanvasNodeType.Audio;
|
||||
const hasImage = isImage && Boolean(node.metadata?.content);
|
||||
const copyImagePrompt = (target: CanvasNodeData) => {
|
||||
const prompt = target.metadata?.prompt?.trim();
|
||||
const prompt = nodeGenerationPrompt(target).trim();
|
||||
if (!prompt) {
|
||||
message.warning("暂无可复制的提示词");
|
||||
return;
|
||||
@@ -588,10 +589,10 @@ export function CanvasNodeInfoModal({ node, open, onClose, onMetadataChange, rea
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
{node.metadata?.prompt ? (
|
||||
{nodeGenerationPrompt(node) ? (
|
||||
<section className="canvas-node-inspector-section">
|
||||
<div className="canvas-node-inspector-section-heading"><span>提示词</span></div>
|
||||
<div className="canvas-node-inspector-copy canvas-node-inspector-prompt">{node.metadata.prompt}</div>
|
||||
<div className="canvas-node-inspector-copy canvas-node-inspector-prompt">{nodeGenerationPrompt(node)}</div>
|
||||
</section>
|
||||
) : null}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user