auto-save 2026-05-20 22:43 (~2)

This commit is contained in:
2026-05-20 22:43:19 +08:00
parent 7106f3ac80
commit 33f87eb35d
2 changed files with 269 additions and 8 deletions

View File

@@ -151,6 +151,8 @@ function sortTemplatesByAnchor<T extends { id: string; anchorTemplateId?: string
return sorted;
}
const PACK_ASSET_CONCURRENCY = 4;
export async function cleanupCharacterAnchor(opts: {
session: GenSession;
sourceImage: GenImage;
@@ -306,7 +308,9 @@ export async function generateAssetPack(opts: {
status: 'draft',
};
for (const template of templates) {
const remainingTemplates = [...templates];
const generatedTemplateIds = new Set<string>();
async function createAsset(template: AssetTemplate): Promise<ToyAsset> {
const assetId = `${opts.kind}_${template.filenamePart}_${randomBytes(3).toString('hex')}`;
const anchorAsset = template.anchorTemplateId
? assets.find(asset => asset.templateId === template.anchorTemplateId)
@@ -318,7 +322,7 @@ export async function generateAssetPack(opts: {
const prompt = renderPrompt(template.promptTemplate, characterSpec, anchorImageUrl);
const preFilledSlot = opts.session.preFilledSlots?.find(slot => slot.templateId === template.id);
if (preFilledSlot) {
assets.push({
return {
id: assetId,
templateId: template.id,
kind: opts.kind,
@@ -346,9 +350,7 @@ export async function generateAssetPack(opts: {
templateFreezeVersion: TEMPLATE_FREEZE_VERSION,
anchorTemplateId: template.anchorTemplateId,
},
});
await opts.onProgress?.(pack);
continue;
};
}
const generated = await generateAssetImage({
packId,
@@ -357,7 +359,7 @@ export async function generateAssetPack(opts: {
anchorImageUrl,
aspectRatio: template.aspectRatio,
});
assets.push({
return {
id: assetId,
templateId: template.id,
kind: opts.kind,
@@ -381,10 +383,31 @@ export async function generateAssetPack(opts: {
anchorTemplateId: template.anchorTemplateId,
raw: generated.raw,
},
});
await opts.onProgress?.(pack);
};
}
while (remainingTemplates.length > 0) {
const readyTemplates = remainingTemplates
.filter(template => !template.anchorTemplateId || generatedTemplateIds.has(template.anchorTemplateId))
.slice(0, PACK_ASSET_CONCURRENCY);
if (!readyTemplates.length) {
throw new Error(`template anchor cycle or missing root: ${remainingTemplates.map(template => template.id).join(', ')}`);
}
for (const template of readyTemplates) {
remainingTemplates.splice(remainingTemplates.indexOf(template), 1);
}
await Promise.all(readyTemplates.map(async template => {
const asset = await createAsset(template);
assets.push(asset);
generatedTemplateIds.add(template.id);
await opts.onProgress?.(pack);
}));
}
const templateOrder = new Map(templates.map((template, index) => [template.id, index]));
assets.sort((a, b) => (templateOrder.get(a.templateId) ?? 0) - (templateOrder.get(b.templateId) ?? 0));
pack.status = 'complete';
const manifest: ExportManifest = {