ai-chatbot/lib/agents/generation-project-state.ts
Your Name 98fe210b64
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled
feat: separate agent projects from canvas storage
2026-03-19 13:07:39 +08:00

160 lines
6.0 KiB
TypeScript

import {
createEmptyAgentModeWorkspaceState,
normalizeAgentModeWorkspaceState,
} from "@/lib/agents/mode-workspace-state";
import {
createEmptyAgentWorkflowMaterialSelections,
normalizeAgentWorkflowMaterialSelections,
} from "@/lib/agents/workflow-material-config";
import type {
AgentGenerationProjectPersistedState,
AgentGenerationProjectWorkspaceState,
AgentWorkflowPersistedState,
} from "@/types/agent";
export function createEmptyAgentGenerationProjectWorkspaceState(): AgentGenerationProjectWorkspaceState {
return {
input: "",
attachments: [],
selectedModelId: "auto",
imageParams: {
aspectRatio: "auto",
imageSize: "2K",
imageCount: 1,
},
};
}
export function createEmptyAgentWorkflowPersistedState(): AgentWorkflowPersistedState {
return {
inputs: {
primarySku: "",
secondarySku: "",
brand: "",
store: "",
},
materials: createEmptyAgentWorkflowMaterialSelections(),
selections: {},
selectedBrandModel: null,
selectedAgentPresetId: null,
currentStage: "workflow",
agentModeState: createEmptyAgentModeWorkspaceState(),
};
}
export function createEmptyAgentGenerationProjectPersistedState(): AgentGenerationProjectPersistedState {
return {
workflowState: createEmptyAgentWorkflowPersistedState(),
workspaceState: createEmptyAgentGenerationProjectWorkspaceState(),
resultImageUrls: [],
};
}
function normalizeWorkspaceState(value: unknown): AgentGenerationProjectWorkspaceState {
const raw =
value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: {};
const attachments = Array.isArray(raw.attachments)
? raw.attachments
.map((item) => {
if (!item || typeof item !== "object" || Array.isArray(item)) {
return null;
}
const record = item as Record<string, unknown>;
const url = String(record.url || "").trim();
if (!url) return null;
return {
url,
name: String(record.name || "").trim() || null,
contentType: String(record.contentType || "").trim() || null,
assetId: String(record.assetId || "").trim() || null,
};
})
.slice(0, 16)
: [];
const rawImageParams =
raw.imageParams && typeof raw.imageParams === "object" && !Array.isArray(raw.imageParams)
? (raw.imageParams as Record<string, unknown>)
: {};
const imageCount = Number(rawImageParams.imageCount);
return {
input: String(raw.input || "").trim(),
attachments,
selectedModelId: String(raw.selectedModelId || "").trim() || "auto",
imageParams: {
aspectRatio: String(rawImageParams.aspectRatio || "").trim() || "auto",
imageSize: String(rawImageParams.imageSize || "").trim() || "2K",
imageCount: Number.isFinite(imageCount) ? Math.max(1, Math.min(8, Math.round(imageCount))) : 1,
},
};
}
function normalizeWorkflowState(value: unknown): AgentWorkflowPersistedState {
const raw =
value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: {};
return {
inputs: {
primarySku: String(raw.inputs && typeof raw.inputs === "object" ? (raw.inputs as Record<string, unknown>).primarySku || "" : "").trim(),
secondarySku: String(raw.inputs && typeof raw.inputs === "object" ? (raw.inputs as Record<string, unknown>).secondarySku || "" : "").trim(),
brand: String(raw.inputs && typeof raw.inputs === "object" ? (raw.inputs as Record<string, unknown>).brand || "" : "").trim(),
store: String(raw.inputs && typeof raw.inputs === "object" ? (raw.inputs as Record<string, unknown>).store || "" : "").trim(),
},
materials: normalizeAgentWorkflowMaterialSelections(raw.materials),
selections:
raw.selections && typeof raw.selections === "object" && !Array.isArray(raw.selections)
? (raw.selections as Record<string, string>)
: {},
selectedBrandModel:
raw.selectedBrandModel && typeof raw.selectedBrandModel === "object" && !Array.isArray(raw.selectedBrandModel)
? {
...(raw.selectedBrandModel as Record<string, unknown>),
brandName: String((raw.selectedBrandModel as Record<string, unknown>).brandName || "").trim(),
id: String((raw.selectedBrandModel as Record<string, unknown>).id || "").trim(),
imageUrl: String((raw.selectedBrandModel as Record<string, unknown>).imageUrl || "").trim(),
assetId: String((raw.selectedBrandModel as Record<string, unknown>).assetId || "").trim() || null,
displayName: String((raw.selectedBrandModel as Record<string, unknown>).displayName || "").trim() || null,
mimeType: String((raw.selectedBrandModel as Record<string, unknown>).mimeType || "").trim() || null,
sortOrder: Number.isFinite(Number((raw.selectedBrandModel as Record<string, unknown>).sortOrder))
? Math.max(0, Math.min(999, Math.round(Number((raw.selectedBrandModel as Record<string, unknown>).sortOrder))))
: 0,
}
: null,
selectedAgentPresetId: String(raw.selectedAgentPresetId || "").trim() || null,
currentStage: raw.currentStage === "mode" ? "mode" : "workflow",
agentModeState: normalizeAgentModeWorkspaceState(raw.agentModeState),
};
}
export function normalizeAgentGenerationProjectPersistedState(
value: unknown
): AgentGenerationProjectPersistedState {
const raw =
value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
: {};
const resultImageUrls = Array.isArray(raw.resultImageUrls)
? Array.from(
new Set(
raw.resultImageUrls
.map((item) => String(item || "").trim())
.filter((item) => /^https?:\/\//i.test(item))
)
).slice(0, 64)
: [];
return {
workflowState: normalizeWorkflowState(raw.workflowState),
workspaceState: normalizeWorkspaceState(raw.workspaceState),
resultImageUrls,
};
}