Files
ttstd-infinite-canvas/web/src/lib/generation-workflow-execution.ts
2026-09-14 01:11:56 +08:00

80 lines
3.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { normalizeRunningHubCapability, type AiConfig, type RunningHubCapability, type RunningHubWorkflowKind, type WorkflowFieldMapping } from "@/stores/use-config-store";
import { workflowProviderPluginEnabled } from "@/lib/plugins/builtin/workflows";
import { usePluginStore } from "@/stores/use-plugin-store";
export type GenerationWorkflowMode = "text" | "image" | "video" | "audio";
export type GenerationWorkflowExecution = {
provider: "runninghub";
kind: RunningHubWorkflowKind;
capability: RunningHubCapability;
interfaceType: string;
name: string;
taskModel: string;
providerModel: string;
workflowId: string;
webappId: string;
workflowJson: Record<string, unknown>;
workflowFields: WorkflowFieldMapping[];
};
// 画布样式计划、任务记录和后端协议必须共用同一个工作流选择结果,避免再次回退到普通模型。
export function resolveGenerationWorkflowExecution(config: AiConfig, mode: GenerationWorkflowMode): GenerationWorkflowExecution | null {
const workflowProvider = mode === "text" ? "model" : config.taskWorkflowProvider || "model";
if (workflowProvider === "model") return null;
if (workflowProvider === "runninghub") {
if (!workflowProviderPluginEnabled(usePluginStore.getState().runtimeStatuses, "runninghub")) throw new Error("RunningHub 工作流插件未启用");
const runningHub = config.runningHub;
const workflowId = runningHub.workflowId.trim();
const kind = runningHub.selectedKind === "app" ? "app" : "workflow";
// RunningHub 工作流的参数拉取、提交和轮询固定使用积分 API Key;企业级 Key 只用于素材上传。
const apiKey = runningHub.apiKey;
if (!runningHub.enabled || !runningHub.baseUrl.trim() || !apiKey.trim() || !workflowId) {
throw new Error("RunningHub 工作流配置不完整,请填写积分 API Key 并选择已保存条目");
}
const workflow = runningHub.workflows.find((item) => item.workflowId.trim() === workflowId && (item.kind === "app" ? "app" : "workflow") === kind);
if (!workflow) throw new Error("当前 RunningHub 工作流条目不存在,请重新选择已保存条目");
const capability = normalizeRunningHubCapability(workflow.capability, normalizeRunningHubCapability(runningHub.capability));
assertWorkflowCapability("RunningHub", capability, mode);
const webappId = kind === "app" ? (workflow.webappId || workflow.workflowId).trim() : "";
const name = workflow.title?.trim() || webappId || workflowId;
return {
provider: "runninghub",
kind,
capability,
interfaceType: `runninghub-workflow-${capability}`,
name,
taskModel: workflowTaskModel("RunningHub · ", name),
providerModel: workflowId,
workflowId: kind === "workflow" ? workflowId : "",
webappId,
workflowJson: workflow.workflowJson || {},
workflowFields: workflow.fields || [],
};
}
throw new Error("未知工作流提供方");
}
function assertWorkflowCapability(providerName: string, capability: RunningHubCapability, mode: GenerationWorkflowMode) {
if (capability === mode) return;
const capabilityName = workflowCapabilityName(capability);
const modeName = workflowCapabilityName(mode);
throw new Error(`${providerName} 已保存条目的用途为${capabilityName},当前节点是${modeName}生成,请切换匹配的工作流`);
}
function workflowCapabilityName(value: GenerationWorkflowMode) {
if (value === "video") return "视频";
if (value === "audio") return "音频";
if (value === "text") return "文本";
return "图片";
}
function workflowTaskModel(prefix: string, name: string) {
return `${prefix}${Array.from(name)
.slice(0, Math.max(0, 120 - prefix.length))
.join("")}`;
}