feat: compose + text-to-image generation modes (multi-image + free-text)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XNQ8ghPfzAfsyVYd6HgFb6
This commit is contained in:
+31
-12
@@ -14,12 +14,19 @@ export const GET: APIRoute = async ({ locals }) => {
|
||||
return json({ jobs: rows });
|
||||
};
|
||||
|
||||
// Body: { recipeId?, recipe?, sources:[{source_path, filename, source_quality?}], origin? }
|
||||
// Body: { recipeId?, recipe?, sources:[{source_path, filename, source_quality?}],
|
||||
// mode?: 'each'|'compose'|'generate', prompt_text?, origin? }
|
||||
export const POST: APIRoute = async ({ request, locals }) => {
|
||||
if (!locals.user) return new Response('Unauthorized', { status: 401 });
|
||||
const b = await request.json();
|
||||
const mode: 'each' | 'compose' | 'generate' = ['each', 'compose', 'generate'].includes(b.mode) ? b.mode : 'each';
|
||||
const sources: any[] = b.sources || [];
|
||||
if (!sources.length) return json({ error: 'Keine Bilder.' }, 400);
|
||||
const promptText: string = (b.prompt_text || '').trim();
|
||||
|
||||
if (mode === 'each' && !sources.length) return json({ error: 'Keine Bilder.' }, 400);
|
||||
if (mode === 'compose' && sources.length < 2) return json({ error: 'Zum Kombinieren mindestens 2 Bilder.' }, 400);
|
||||
if (mode === 'compose' && !promptText) return json({ error: 'Bitte beschreiben, was entstehen soll.' }, 400);
|
||||
if (mode === 'generate' && !promptText) return json({ error: 'Bitte einen Text eingeben.' }, 400);
|
||||
|
||||
let snapshot: any = b.recipe;
|
||||
if (b.recipeId) {
|
||||
@@ -27,11 +34,11 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
||||
if (!r) return json({ error: 'Rezept nicht gefunden.' }, 404);
|
||||
snapshot = r;
|
||||
}
|
||||
if (!snapshot) return json({ error: 'Kein Rezept.' }, 400);
|
||||
snapshot = snapshot || {};
|
||||
|
||||
// Rezept-Snapshot einfrieren
|
||||
const snap = {
|
||||
tasks: snapshot.tasks || [],
|
||||
tasks: snapshot.tasks || (mode === 'each' ? [] : []),
|
||||
output_format: snapshot.output_format,
|
||||
orientation: snapshot.orientation,
|
||||
crop_mode: snapshot.crop_mode || 'crop',
|
||||
@@ -39,21 +46,33 @@ export const POST: APIRoute = async ({ request, locals }) => {
|
||||
contour_mm: snapshot.contour_mm ?? null,
|
||||
model_key: snapshot.model_key ?? null,
|
||||
custom_instruction: snapshot.custom_instruction ?? null,
|
||||
prompt_text: promptText || null,
|
||||
delivery: snapshot.delivery || 'library',
|
||||
picdrop_gallery: snapshot.picdrop_gallery ?? null,
|
||||
};
|
||||
|
||||
const total = (mode === 'each') ? sources.length : 1;
|
||||
const job = await one<{ id: string }>(
|
||||
`INSERT INTO jobs (created_by, origin, recipe_snapshot, status, total)
|
||||
VALUES ($1,$2,$3,'queued',$4) RETURNING id`,
|
||||
[locals.user.uid, b.origin || 'web', JSON.stringify(snap), sources.length]);
|
||||
`INSERT INTO jobs (created_by, origin, mode, recipe_snapshot, status, total)
|
||||
VALUES ($1,$2,$3,$4,'queued',$5) RETURNING id`,
|
||||
[locals.user.uid, b.origin || 'web', mode, JSON.stringify(snap), total]);
|
||||
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
const s = sources[i];
|
||||
if (mode === 'each') {
|
||||
for (let i = 0; i < sources.length; i++) {
|
||||
const s = sources[i];
|
||||
const item = await one<{ id: string }>(
|
||||
`INSERT INTO items (job_id, position, status, source_path, filename, source_quality)
|
||||
VALUES ($1,$2,'queued',$3,$4,$5) RETURNING id`,
|
||||
[job!.id, i, s.source_path, s.filename || null, s.source_quality || 'original']);
|
||||
await enqueue({ itemId: item!.id, jobId: job!.id });
|
||||
}
|
||||
} else {
|
||||
const srcPaths = sources.map((s) => s.source_path).filter(Boolean);
|
||||
const base = mode === 'generate' ? 'neu' : 'kombiniert';
|
||||
const item = await one<{ id: string }>(
|
||||
`INSERT INTO items (job_id, position, status, source_path, filename, source_quality)
|
||||
VALUES ($1,$2,'queued',$3,$4,$5) RETURNING id`,
|
||||
[job!.id, i, s.source_path, s.filename || null, s.source_quality || 'original']);
|
||||
`INSERT INTO items (job_id, position, status, source_paths, filename, source_quality)
|
||||
VALUES ($1,0,'queued',$2,$3,'original') RETURNING id`,
|
||||
[job!.id, srcPaths.length ? JSON.stringify(srcPaths) : null, base]);
|
||||
await enqueue({ itemId: item!.id, jobId: job!.id });
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user