import { defaultAgentWorkflowUiConfig, flattenVisibleAgentWorkflowSteps, getAgentWorkflowSelectedOptionPath, getEnabledAgentWorkflowStepTree, isAgentWorkflowStepSelectionComplete, } from "@/lib/agents/workflow-ui-config"; import type { AgentWorkflowComposerContext, AgentWorkflowMaterialSelections, AgentWorkflowReferenceImage, AgentWorkflowSelectedBrandModel, AgentWorkflowStepKey, AgentWorkflowUiConfig, } from "@/types/agent"; export interface AgentWorkflowInputsValue { primarySku: string; secondarySku: string; brand: string; store: string; priceBand: string; } export function buildAgentWorkflowComposerContext(params: { config?: AgentWorkflowUiConfig | null; inputs: AgentWorkflowInputsValue; materials?: AgentWorkflowMaterialSelections | null; selectedBrandModel?: AgentWorkflowSelectedBrandModel | null; selections: Partial>; }): AgentWorkflowComposerContext | null { const config = params.config || defaultAgentWorkflowUiConfig; const steps = flattenVisibleAgentWorkflowSteps( getEnabledAgentWorkflowStepTree(Array.isArray(config.steps) ? config.steps : []), params.selections ) .map(({ step }) => step) .filter((step) => Array.isArray(step.options) && step.options.length > 0); const selections = steps .map((step) => { const selectedOptions = getAgentWorkflowSelectedOptionPath({ step, selectionValue: params.selections[step.key], }); if (selectedOptions.length === 0) return []; return selectedOptions.map((option) => ({ stepKey: step.key, stepTitle: step.title, optionKey: option.key, optionName: option.buttonName, promptFragment: option.promptFragment || option.buttonName, })); }) .flat() as AgentWorkflowComposerContext["selections"]; const referenceImages = getSelectedWorkflowReferenceImages({ inputs: params.inputs, materials: params.materials, selectedBrandModel: params.selectedBrandModel, }); const summaryParts: string[] = []; if (params.inputs.primarySku.trim()) { summaryParts.push(`主SKU:${params.inputs.primarySku.trim()}`); } if (params.inputs.secondarySku.trim()) { summaryParts.push(`搭配SKU:${params.inputs.secondarySku.trim()}`); } if (params.inputs.brand.trim()) { summaryParts.push(`品牌:${params.inputs.brand.trim()}`); } if (params.inputs.store.trim()) { summaryParts.push(`店铺:${params.inputs.store.trim()}`); } if (params.inputs.priceBand.trim()) { summaryParts.push(`价格带:${params.inputs.priceBand.trim()}`); } if (referenceImages.some((item) => item.source === "primary")) { summaryParts.push( `主SPU图:${referenceImages.filter((item) => item.source === "primary").length}张` ); } if (referenceImages.some((item) => item.source === "secondary")) { summaryParts.push( `搭配SKU图:${referenceImages.filter((item) => item.source === "secondary").length}张` ); } if (referenceImages.some((item) => item.source === "brandModel")) { summaryParts.push( `品牌模特图:${referenceImages.filter((item) => item.source === "brandModel").length}张` ); } selections.forEach((item) => { summaryParts.push(`${item.stepTitle}:${item.optionName}`); }); if (summaryParts.length === 0) { return null; } const promptLines: string[] = []; if (params.inputs.primarySku.trim()) { promptLines.push(`主SKU:${params.inputs.primarySku.trim()}`); } if (params.inputs.secondarySku.trim()) { promptLines.push(`搭配SKU:${params.inputs.secondarySku.trim()}`); } if (params.inputs.brand.trim()) { promptLines.push(`品牌:${params.inputs.brand.trim()}`); } if (params.inputs.store.trim()) { promptLines.push(`店铺:${params.inputs.store.trim()}`); } if (params.inputs.priceBand.trim()) { promptLines.push(`价格带:${params.inputs.priceBand.trim()}`); } if (referenceImages.some((item) => item.source === "primary")) { const labels = referenceImages .filter((item) => item.source === "primary") .map((item) => item.label) .filter(Boolean) .slice(0, 8); promptLines.push( `主SPU参考图:已选${referenceImages.filter((item) => item.source === "primary").length}张${ labels.length > 0 ? `(${labels.join("、")})` : "" }` ); } if (referenceImages.some((item) => item.source === "secondary")) { const labels = referenceImages .filter((item) => item.source === "secondary") .map((item) => item.label) .filter(Boolean) .slice(0, 8); promptLines.push( `搭配SKU参考图:已选${referenceImages.filter((item) => item.source === "secondary").length}张${ labels.length > 0 ? `(${labels.join("、")})` : "" }` ); } if (referenceImages.some((item) => item.source === "brandModel")) { const labels = referenceImages .filter((item) => item.source === "brandModel") .map((item) => item.label) .filter(Boolean) .slice(0, 8); promptLines.push( `品牌模特图:已选${referenceImages.filter((item) => item.source === "brandModel").length}张${ labels.length > 0 ? `(${labels.join("、")})` : "" }` ); } selections.forEach((item) => { promptLines.push(`${item.stepTitle}:${item.promptFragment || item.optionName}`); }); return { primarySku: params.inputs.primarySku.trim() || undefined, secondarySku: params.inputs.secondarySku.trim() || undefined, brand: params.inputs.brand.trim() || undefined, store: params.inputs.store.trim() || undefined, priceBand: params.inputs.priceBand.trim() || undefined, selections, referenceImages, summaryText: summaryParts.join(" / "), promptText: promptLines.join("\n"), }; } export function getSelectedWorkflowReferenceImages(params: { inputs: AgentWorkflowInputsValue; materials?: AgentWorkflowMaterialSelections | null; selectedBrandModel?: AgentWorkflowSelectedBrandModel | null; }): AgentWorkflowReferenceImage[] { const materials = params.materials; if (!materials) return []; const collect = ( source: "primary" | "secondary", sourceLabel: string, fallbackSku: string ) => { const state = materials[source]; const result = state?.result; if (!result || !Array.isArray(result.images) || result.images.length === 0) { return [] as AgentWorkflowReferenceImage[]; } const selectedIds = new Set( (state.selectedImageIds || []).map((item) => String(item || "").trim()).filter(Boolean) ); if (selectedIds.size === 0) { return [] as AgentWorkflowReferenceImage[]; } return result.images .filter((item) => selectedIds.has(item.id)) .map((item) => ({ id: item.id, source, sourceLabel, sku: result.matchedSku || fallbackSku || undefined, productModel: result.productModel || null, label: item.label, name: item.fileName || item.label, url: item.imageUrl, assetId: item.assetId || null, mimeType: item.mimeType || null, })); }; return [ ...collect("primary", "主SPU", params.inputs.primarySku.trim()), ...collect("secondary", "搭配SKU", params.inputs.secondarySku.trim()), ...(params.selectedBrandModel?.imageUrl ? [ { id: params.selectedBrandModel.id, source: "brandModel" as const, sourceLabel: "品牌模特", label: params.selectedBrandModel.displayName || params.selectedBrandModel.brandName, name: params.selectedBrandModel.displayName || params.selectedBrandModel.brandName, url: params.selectedBrandModel.imageUrl, assetId: params.selectedBrandModel.assetId || null, mimeType: params.selectedBrandModel.mimeType || null, }, ] : []), ]; } export function getAgentWorkflowProgress(params: { config?: AgentWorkflowUiConfig | null; selections: Partial>; }) { const config = params.config || defaultAgentWorkflowUiConfig; const enabledSteps = flattenVisibleAgentWorkflowSteps( getEnabledAgentWorkflowStepTree(config.steps || []), params.selections ) .map(({ step }) => step) .filter((step) => Array.isArray(step.options) && step.options.length > 0); const completedSteps = enabledSteps.filter((step) => { return isAgentWorkflowStepSelectionComplete({ step, selectionValue: params.selections[step.key], }); }); return { total: enabledSteps.length, completed: completedSteps.length, isComplete: enabledSteps.length > 0 && completedSteps.length === enabledSteps.length, }; }