bilder gen
This commit is contained in:
@@ -283,7 +283,11 @@ const TABLES = [
|
||||
str('merkmale', 255, { array: true }),
|
||||
str('change_reason', 512),
|
||||
id('won_against_version_id'), // Vorher/Nachher-Vote
|
||||
id('reference_file_ids', { array: true }), // → Bucket asset-references
|
||||
id('reference_file_ids', { array: true }), // EINGABE: hochgeladene Referenzen
|
||||
// ERGEBNIS: das für diese Version erzeugte Bild. Bewusst getrennt von
|
||||
// `reference_file_ids` – sonst ließe sich später nicht mehr unterscheiden,
|
||||
// was der Nutzer beigesteuert und was das KI-Modell erzeugt hat.
|
||||
id('bild_file_id'), // → Bucket generated-images
|
||||
id('einwilligung_file_id'), // → Bucket consents
|
||||
],
|
||||
indexes: [{ key: 'idx_asset', type: 'key', columns: ['asset_id', 'version_no'] }],
|
||||
@@ -362,9 +366,19 @@ const TABLES = [
|
||||
enm('typ', [
|
||||
'bild_gen', 'video_gen', 'tagging', 'vergleich', 'script',
|
||||
'slot_analyse', 'ordner_vorschlag', 'werbetext', // P19, P20, P21
|
||||
// Eigener Typ statt `bild_gen` mitzubenutzen: Modell-Generierung hat
|
||||
// andere Kosten, andere Fehlerbilder und einen anderen Ergebnis-Screen.
|
||||
// Alles über `refs` zu unterscheiden, macht Kostenauswertung und
|
||||
// Prompt-Debugging unnötig mühsam.
|
||||
'modell_gen',
|
||||
], { required: true }),
|
||||
str('prompt_template_key', 16), // welcher Prompt …
|
||||
int('prompt_template_version'), // … in welcher Version lief
|
||||
// 🔒 Was wirklich ans Modell ging. projekt-uebersicht.md §9 führt
|
||||
// `jobs.prompt_sent` als eines der drei Felder, die exklusiv dem internen
|
||||
// Team gehören – im Schema fehlte es bisher. Ohne dieses Feld ist bei
|
||||
// Job-Typen ohne eigene Ergebnis-Tabelle kein Prompt-Debugging möglich.
|
||||
md('prompt_sent'),
|
||||
enm('status', ['wartend', 'laeuft', 'fertig', 'fehler'], { default: 'wartend' }),
|
||||
flt('cost_usd'), int('tokens'),
|
||||
str('error', 4096),
|
||||
@@ -540,6 +554,63 @@ const BUCKETS = [
|
||||
{ id: 'generated-images', name: 'Generierte Bilder' },
|
||||
];
|
||||
|
||||
/**
|
||||
* Zieht fehlende Enum-Werte auf einer bestehenden Spalte nach.
|
||||
*
|
||||
* Der Plan hat das lange als gefährlich geführt (§2.6: „je nach Version Löschen
|
||||
* und Neuanlegen der Spalte, also Datenverlust"). **Für Appwrite 1.8.1 ist das
|
||||
* am 15.08.2026 gegen eine Wegwerf-Tabelle geprüft worden:** `PATCH` auf die
|
||||
* Enum-Spalte liefert 200, alle Bestandswerte überleben, der neue Wert ist
|
||||
* sofort nutzbar. Bei einem Server-Upgrade gehört dieser Test wiederholt.
|
||||
*
|
||||
* Bewusst nur **additiv**: Werte, die live existieren und im Skript fehlen,
|
||||
* werden gemeldet, aber nie entfernt – sonst verlören bestehende Zeilen ihren
|
||||
* Wert, und genau davor warnt der Plan zu Recht.
|
||||
*/
|
||||
/**
|
||||
* Enum-Spalten, die **nie** automatisch nachgezogen werden.
|
||||
*
|
||||
* `prompt_templates.key` ist mit 22 Zeilen gefüllt und trägt die Identität
|
||||
* jedes Prompts. Selbst wenn der additive PATCH technisch hält – hier ist jede
|
||||
* Enum-Berührung ein Migrationsprojekt mit Prüfung, kein Skriptlauf.
|
||||
*/
|
||||
const ENUM_TABU = new Set(['prompt_templates.key']);
|
||||
|
||||
async function enumNachziehen(tableId, c, live) {
|
||||
const key = c.body.key;
|
||||
if (c.type !== 'enum') { skipped++; console.log(` = ${tableId}.${key} (existiert)`); return; }
|
||||
|
||||
if (ENUM_TABU.has(`${tableId}.${key}`)) {
|
||||
const fehlt = (c.body.elements ?? []).filter((e) => !(live.elements ?? []).includes(e));
|
||||
if (fehlt.length) {
|
||||
warned++;
|
||||
console.warn(` ! ${tableId}.${key}: [${fehlt.join(', ')}] fehlen – NICHT automatisch geändert (Tabu-Liste), bitte bewusst migrieren`);
|
||||
} else { skipped++; console.log(` = ${tableId}.${key} (existiert)`); }
|
||||
return;
|
||||
}
|
||||
|
||||
const soll = c.body.elements ?? [];
|
||||
const ist = live.elements ?? [];
|
||||
const fehlend = soll.filter((e) => !ist.includes(e));
|
||||
const zusaetzlich = ist.filter((e) => !soll.includes(e));
|
||||
|
||||
if (zusaetzlich.length) {
|
||||
warned++;
|
||||
console.warn(` ! ${tableId}.${key}: live zusätzlich [${zusaetzlich.join(', ')}] – bleibt stehen, wird nicht entfernt`);
|
||||
}
|
||||
if (!fehlend.length) { skipped++; console.log(` = ${tableId}.${key} (existiert)`); return; }
|
||||
|
||||
const body = {
|
||||
elements: [...ist, ...fehlend],
|
||||
required: !!c.body.required,
|
||||
default: c.body.required ? null : (c.body.default ?? null),
|
||||
};
|
||||
await ensure(`${tableId}.${key} +[${fehlend.join(',')}]`, 'PATCH',
|
||||
`/tablesdb/${DB_ID}/tables/${tableId}/columns/enum/${key}`, body);
|
||||
updated++; created--; // ensure() zählt als "angelegt" – hier ist es eine Änderung
|
||||
await waitForColumn(tableId, key);
|
||||
}
|
||||
|
||||
// ---- Ablauf ---------------------------------------------------------------
|
||||
async function waitForColumn(tableId, key) {
|
||||
for (let i = 0; i < 30; i++) {
|
||||
@@ -592,8 +663,11 @@ async function main() {
|
||||
for (const c of t.columns) {
|
||||
// Erst GET: Appwrite prüft das Zeilengrößen-Limit VOR dem Duplikat-Check,
|
||||
// ein erneutes POST auf große Spalten gäbe sonst 400 statt 409.
|
||||
const { status } = await api('GET', `/tablesdb/${DB_ID}/tables/${t.id}/columns/${c.body.key}`);
|
||||
if (status === 200) { skipped++; console.log(` = ${t.id}.${c.body.key} (existiert)`); continue; }
|
||||
const { status, json } = await api('GET', `/tablesdb/${DB_ID}/tables/${t.id}/columns/${c.body.key}`);
|
||||
if (status === 200) {
|
||||
await enumNachziehen(t.id, c, json);
|
||||
continue;
|
||||
}
|
||||
await ensure(`${t.id}.${c.body.key}`, 'POST', `/tablesdb/${DB_ID}/tables/${t.id}/columns/${c.type}`, c.body);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user