feat(canvas): 生成合同 - 统一节点参数并补充模型上下文能力

This commit is contained in:
ddCat committed 2026-09-19 20:32:05 +08:00
1 parent a59b77cf70
commit 3bf21d79af
18 files changed
+965 -40

No files matched your search

@@ -6,6 +6,7 @@ import { ArrowLeftRight, ArrowUp, AtSign, Boxes, Camera, ChevronDown, FileText,
import { ModelPicker } from "@/components/model-picker";
import { defaultConfig, modelOptionName, resolveModelChannel, useEffectiveConfig, type AiConfig } from "@/stores/use-config-store";
import { resolveCanvasGenerationModel } from "@/lib/canvas/canvas-project-generation";
import { canonicalGenerationMetadata } from "@/lib/canvas/generation-contract";
import { clampPromptEditorModalSize, PROMPT_EDITOR_VIEWPORT_MARGIN } from "@/lib/canvas/canvas-prompt-editor-size";
import { CreditSymbol, requestCreditCost } from "@/constant/credits";
import { canvasThemes } from "@/lib/canvas-theme";
@@ -78,6 +79,7 @@ export function CanvasNodePromptPanel({ projectId, node, isRunning, onPromptChan
const promptOptimizerEnabled = usePluginStore((state) => state.pluginStates[PROMPT_OPTIMIZER_PLUGIN_ID]?.effectiveEnabled ?? Boolean(state.installations.find((item) => item.manifest.id === PROMPT_OPTIMIZER_PLUGIN_ID)?.enabled));
const simpleMode = workspaceMode === "simple";
const mode = defaultMode(node.type);
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 ?? "";
@@ -106,17 +108,17 @@ export function CanvasNodePromptPanel({ projectId, node, isRunning, onPromptChan
characterCount: activeReferences.filter((item) => item.kind === "character").length,
},
videoOperation: node.metadata?.videoEditOperation,
videoSeconds: mode === "video" ? node.metadata?.seconds || globalConfig.videoSeconds : undefined,
videoSeconds: mode === "video" ? node.metadata?.seconds ?? globalConfig.videoSeconds : undefined,
options: modelRequestOptions({
...globalConfig,
size: node.metadata?.size || globalConfig.size,
quality: node.metadata?.quality || globalConfig.quality,
count: String(node.metadata?.count || globalConfig.count),
transparentBackground: node.metadata?.transparentBackground || globalConfig.transparentBackground,
videoSeconds: node.metadata?.seconds || globalConfig.videoSeconds,
videoSeconds: node.metadata?.seconds ?? globalConfig.videoSeconds,
vquality: node.metadata?.vquality || globalConfig.vquality,
videoGenerateAudio: node.metadata?.generateAudio || globalConfig.videoGenerateAudio,
videoWatermark: node.metadata?.watermark || globalConfig.videoWatermark,
videoGenerateAudio: node.metadata?.generateAudio ?? globalConfig.videoGenerateAudio,
videoWatermark: node.metadata?.watermark ?? globalConfig.videoWatermark,
audioVoice: node.metadata?.audioVoice || globalConfig.audioVoice,
audioFormat: node.metadata?.audioFormat || globalConfig.audioFormat,
audioSpeed: node.metadata?.audioSpeed || globalConfig.audioSpeed,
@@ -1034,6 +1036,7 @@ function defaultMode(type: CanvasNodeData["type"]): CanvasNodeGenerationMode {
}
export function buildNodeConfig(globalConfig: AiConfig, node: CanvasNodeData, mode: CanvasNodeGenerationMode, requirements: ModelRequirements): AiConfig {
node = { ...node, metadata: canonicalGenerationMetadata(node, mode) };
const defaultModel = mode === "image" ? globalConfig.imageModel : mode === "video" ? globalConfig.videoModel : mode === "audio" ? globalConfig.audioModel : globalConfig.textModel;
const fallbackModel = mode === "image" ? defaultConfig.imageModel : mode === "video" ? defaultConfig.videoModel : mode === "audio" ? defaultConfig.audioModel : defaultConfig.textModel;
const preferredModel = resolveCanvasGenerationModel(globalConfig, node.metadata?.model, mode) || resolveCanvasGenerationModel(globalConfig, defaultModel, mode) || fallbackModel;
@@ -1074,7 +1077,7 @@ export function buildNodeConfig(globalConfig: AiConfig, node: CanvasNodeData, mo
quality: defaults.quality ?? globalConfig.quality ?? defaultConfig.quality,
size: defaults.size ?? globalConfig.size ?? defaultConfig.size,
transparentBackground: defaults.transparentBackground ?? "false",
videoSeconds: defaults.videoSeconds || normalizeVideoDuration(globalConfig.videoSeconds || defaultConfig.videoSeconds),
videoSeconds: defaults.videoSeconds ?? normalizeVideoDuration(globalConfig.videoSeconds ?? defaultConfig.videoSeconds),
vquality: defaults.vquality ?? normalizeVideoResolution(globalConfig.vquality || defaultConfig.vquality),
videoGenerateAudio: defaults.videoGenerateAudio ?? globalConfig.videoGenerateAudio ?? defaultConfig.videoGenerateAudio,
videoWatermark: defaults.videoWatermark ?? globalConfig.videoWatermark ?? defaultConfig.videoWatermark,