@rslsp1/fa-app-tools 2.0.81 → 2.0.83

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/szenen.js CHANGED
@@ -38,6 +38,7 @@ __export(szenen_exports, {
38
38
  ContractViolation: () => ContractViolation,
39
39
  DERIVABLE_TYPES: () => DERIVABLE_TYPES,
40
40
  ELEMENT_VERSION_SCHEMA_FILE: () => ELEMENT_VERSION_SCHEMA_FILE,
41
+ FLOW_MODEL_DISPLAY_NAMES: () => FLOW_MODEL_DISPLAY_NAMES,
41
42
  PROBE_VERSION_ID: () => PROBE_VERSION_ID,
42
43
  REFERENCE_FIELD: () => REFERENCE_FIELD,
43
44
  RULES_WITHOUT_CAPABILITY_EFFECT: () => RULES_WITHOUT_CAPABILITY_EFFECT,
@@ -57,6 +58,7 @@ __export(szenen_exports, {
57
58
  VersionDagError: () => VersionDagError,
58
59
  areasFor: () => areasFor,
59
60
  assessDerivationResponse: () => assessDerivationResponse,
61
+ batchesForPromptRun: () => batchesForPromptRun,
60
62
  buildDerivationSystemInstruction: () => buildSystemInstruction2,
61
63
  buildDerivationUserPrompt: () => buildUserPrompt2,
62
64
  buildSystemInstruction: () => buildSystemInstruction,
@@ -89,6 +91,7 @@ __export(szenen_exports, {
89
91
  checkSzenenBatchOrigin: () => checkSzenenBatchOrigin,
90
92
  checkTitle: () => checkTitle,
91
93
  checkWriteDraftInput: () => checkWriteDraftInput,
94
+ collectImageBatches: () => collectImageBatches,
92
95
  collectImageGenerationOrders: () => collectImageGenerationOrders,
93
96
  collectPromptRuns: () => collectPromptRuns,
94
97
  collectProviderChecks: () => collectProviderChecks,
@@ -102,10 +105,14 @@ __export(szenen_exports, {
102
105
  createEventLogDerivationPersistence: () => createEventLogDerivationPersistence,
103
106
  createEventLogRunPersistence: () => createEventLogRunPersistence,
104
107
  createFakeTextGenerationPort: () => createFakeTextGenerationPort,
108
+ createFlowImageProvider: () => createFlowImageProvider,
105
109
  createFlowSzenenViewPort: () => createFlowSzenenViewPort,
106
110
  createFlowTextGenerationPort: () => createFlowTextGenerationPort,
107
111
  createHfElementStore: () => createHfElementStore,
108
112
  createHfEventChannel: () => createHfEventChannel,
113
+ createHfImageBatchHistory: () => createHfImageBatchHistory,
114
+ createHfImageBatchWrite: () => createHfImageBatchWrite,
115
+ createHfImageGenerationBatchPersistence: () => createHfImageGenerationBatchPersistence,
109
116
  createHfImageLibrary: () => createHfImageLibrary,
110
117
  createImageGenerationPort: () => createImageGenerationPort,
111
118
  createInMemoryEventChannel: () => createInMemoryEventChannel,
@@ -119,12 +126,14 @@ __export(szenen_exports, {
119
126
  differentialSteps: () => differentialSteps,
120
127
  draftRevisionOf: () => draftRevisionOf,
121
128
  elementStoreContractChecks: () => elementStoreContractChecks,
129
+ findImageBatch: () => findImageBatch,
122
130
  findImageGenerationOrder: () => findImageGenerationOrder,
123
131
  findPromptRun: () => findPromptRun,
124
132
  findProviderCheck: () => findProviderCheck,
125
133
  findSceneDerivation: () => findSceneDerivation,
126
134
  findSceneDerivationRecovery: () => findSceneDerivationRecovery,
127
135
  firstError: () => firstError,
136
+ flowImageProviderHasAccess: () => flowImageProviderHasAccess,
128
137
  formatSchemaErrors: () => formatSchemaErrors,
129
138
  freezeDraftChain: () => freezeDraftChain,
130
139
  getSzenenSchemas: () => getSzenenSchemas,
@@ -5327,7 +5336,30 @@ var SZENEN_EVENT_TYPES = {
5327
5336
  * ebenfalls keine Bilddaten — nur Status, Zaehlung und die Item-Kennung,
5328
5337
  * falls eine entstand.
5329
5338
  */
5330
- imageGenerationFinished: "szenen.image_generation_finished"
5339
+ imageGenerationFinished: "szenen.image_generation_finished",
5340
+ /**
5341
+ * Ein Bild-Batch ist kanonisch gespeichert — Stufe 6.9.2, Gate D
5342
+ * (D-6.9.2-6).
5343
+ *
5344
+ * Erscheint erst, **nachdem** jedes Bild des Batches im Bildbestand liegt
5345
+ * (`hfUploadImage` + `image_added`, dieselbe Reihenfolge wie
5346
+ * `hfImageLibrary.putImage`) — kein Bild gilt als vorhanden, bevor sein
5347
+ * Upload bestätigt ist (R3). Trägt bewusst **keine Bilddaten**, nur den
5348
+ * vollständigen Metadatennachweis, den `listBatchesForPromptRun()` /
5349
+ * `getBatch()` ohne MySQL rekonstruieren können müssen: `item_id`,
5350
+ * `prompt_run_id`, `generation_batch_id`, `source_kind`, je Bild
5351
+ * `position`, `media_ref`, `asset_id`, `model`, `seed`, `width`/`height`.
5352
+ *
5353
+ * Additiv wie jedes Ereignis dieser Domain: ein zweiter Batch desselben
5354
+ * Laufs ist ein **weiteres** Ereignis mit derselben `item_id`, nicht eine
5355
+ * Änderung am ersten (D-113/D-121 — ein Lauf bleibt ein Item). Gilt für
5356
+ * `generated_in_app` **und** `external_import` — nur `source_kind`
5357
+ * unterscheidet die beiden Schreiber (D-116/D-117/D-120).
5358
+ *
5359
+ * Der Elementreducer ignoriert auch diesen Typ (`default:`-Zweig); gelesen
5360
+ * wird mit `collectImageBatches` (`imageBatchStore.ts`).
5361
+ */
5362
+ imageBatchPersisted: "szenen.image_batch_persisted"
5331
5363
  };
5332
5364
  function sortForReplay(events) {
5333
5365
  return [...events].sort((a, b) => {
@@ -10996,6 +11028,297 @@ function createClientRunPort(options) {
10996
11028
  };
10997
11029
  }
10998
11030
 
11031
+ // src/lib/szenen/flowImageProvider.ts
11032
+ var FLOW_MODEL_DISPLAY_NAMES = {
11033
+ "imagen-4.0-generate-001": "Imagen 4"
11034
+ };
11035
+ function flowImageProviderHasAccess(model) {
11036
+ return model.callable_model_id in FLOW_MODEL_DISPLAY_NAMES;
11037
+ }
11038
+ function istNichtleererText(wert) {
11039
+ return typeof wert === "string" && wert.trim().length > 0;
11040
+ }
11041
+ function createFlowImageProvider(generateImage) {
11042
+ return {
11043
+ async generate(input) {
11044
+ const modelDisplayName = FLOW_MODEL_DISPLAY_NAMES[input.callableModelId];
11045
+ if (!modelDisplayName) {
11046
+ throw new Error(
11047
+ `Der Flow-Host kennt keinen Flow-Display-Namen zu "${input.callableModelId}". Bekannt sind: ${Object.keys(FLOW_MODEL_DISPLAY_NAMES).join(", ")}. Es wird kein anderes Modell ersatzweise gerufen (D-115/D-6.9.2-3).`
11048
+ );
11049
+ }
11050
+ if (istNichtleererText(input.negativePrompt)) {
11051
+ throw new Error(
11052
+ "Flow.generate.image kennt keinen dokumentierten Parameter f\xFCr einen negativen Prompt. Der Auftrag wird deshalb als fehlgeschlagen protokolliert, statt den negativen Prompt still zu verlieren (D-6.9.2-3)."
11053
+ );
11054
+ }
11055
+ const erzeugt = [];
11056
+ let ersterFehler = null;
11057
+ for (let position = 0; position < input.imageCount; position++) {
11058
+ try {
11059
+ const antwort = await generateImage({
11060
+ prompt: input.positivePrompt,
11061
+ modelDisplayName,
11062
+ ...input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}
11063
+ });
11064
+ if (!antwort || typeof antwort.base64 !== "string" || antwort.base64.length === 0) {
11065
+ throw new Error("Flow.generate.image hat kein Bild geliefert.");
11066
+ }
11067
+ erzeugt.push({
11068
+ imageBase64: antwort.base64,
11069
+ // Das tatsaechlich gerufene Modell, nicht der Flow-Display-Name —
11070
+ // im Bestand soll stehen, was bezahlt wurde (wie reactImageProvider.ts).
11071
+ model: input.callableModelId
11072
+ // Kein Seed: weder als Eingabe dokumentiert noch als Ausgabe
11073
+ // geliefert — nichts wird erfunden (D-107).
11074
+ });
11075
+ } catch (fehler4) {
11076
+ ersterFehler = fehler4 instanceof Error ? fehler4.message : String(fehler4);
11077
+ break;
11078
+ }
11079
+ }
11080
+ if (erzeugt.length === 0) {
11081
+ throw new Error(
11082
+ ersterFehler ?? `Flow.generate.image hat zu ${input.callableModelId} kein verwertbares Bild geliefert.`
11083
+ );
11084
+ }
11085
+ return { images: erzeugt };
11086
+ }
11087
+ };
11088
+ }
11089
+
11090
+ // src/lib/szenen/imageBatchStore.ts
11091
+ var istText4 = (wert) => typeof wert === "string" && wert.trim().length > 0;
11092
+ function alsBilder(rohe) {
11093
+ if (!Array.isArray(rohe)) return [];
11094
+ return rohe.filter((b) => !!b && typeof b === "object").filter((b) => istText4(b.media_ref) && typeof b.position === "number").map((b) => ({
11095
+ media_ref: b.media_ref,
11096
+ position: b.position,
11097
+ ...istText4(b.asset_id) ? { asset_id: b.asset_id } : {},
11098
+ model: b.model ?? null,
11099
+ seed: b.seed ?? null,
11100
+ width: b.width ?? null,
11101
+ height: b.height ?? null
11102
+ }));
11103
+ }
11104
+ function collectImageBatches(events) {
11105
+ const byItemId = /* @__PURE__ */ new Map();
11106
+ for (const event of events) {
11107
+ if (event.type !== SZENEN_EVENT_TYPES.imageBatchPersisted) continue;
11108
+ const payload = event.payload;
11109
+ if (!payload || !istText4(payload.item_id) || !istText4(payload.prompt_run_id) || !istText4(payload.generation_batch_id)) continue;
11110
+ if (payload.source_kind !== "generated_in_app" && payload.source_kind !== "external_import") continue;
11111
+ const bestehend = byItemId.get(payload.item_id);
11112
+ if (bestehend?.generation_batch_ids.includes(payload.generation_batch_id)) continue;
11113
+ const bilder = alsBilder(payload.images);
11114
+ if (!bestehend) {
11115
+ byItemId.set(payload.item_id, {
11116
+ item_id: payload.item_id,
11117
+ prompt_run_id: payload.prompt_run_id,
11118
+ generation_batch_ids: [payload.generation_batch_id],
11119
+ source_kind: payload.source_kind,
11120
+ title: istText4(payload.title) ? payload.title : `Batch aus Lauf ${payload.prompt_run_id}`,
11121
+ images: bilder
11122
+ });
11123
+ continue;
11124
+ }
11125
+ byItemId.set(payload.item_id, {
11126
+ ...bestehend,
11127
+ generation_batch_ids: [...bestehend.generation_batch_ids, payload.generation_batch_id],
11128
+ images: [...bestehend.images, ...bilder]
11129
+ });
11130
+ }
11131
+ return [...byItemId.values()];
11132
+ }
11133
+ function batchesForPromptRun(events, runId) {
11134
+ return collectImageBatches(events).filter((b) => b.prompt_run_id === runId);
11135
+ }
11136
+ function findImageBatch(events, batchId) {
11137
+ return collectImageBatches(events).find((b) => b.generation_batch_ids.includes(batchId)) ?? null;
11138
+ }
11139
+
11140
+ // src/lib/szenen/hfImageBatchHistory.ts
11141
+ function lesefehler(aktion, error) {
11142
+ return {
11143
+ kind: "error",
11144
+ message: `${aktion}: ${error instanceof Error ? error.message : String(error)}`,
11145
+ retryable: true
11146
+ };
11147
+ }
11148
+ function createHfImageBatchHistory(options) {
11149
+ const { channel } = options;
11150
+ return {
11151
+ async listBatchesForPromptRun(runId) {
11152
+ try {
11153
+ const events = await channel.readEvents();
11154
+ return { kind: "ok", value: batchesForPromptRun(events, runId) };
11155
+ } catch (error) {
11156
+ return lesefehler(`Batches fuer Lauf ${runId} konnten nicht gelesen werden`, error);
11157
+ }
11158
+ },
11159
+ async getBatch(batchId) {
11160
+ try {
11161
+ const events = await channel.readEvents();
11162
+ return { kind: "ok", value: findImageBatch(events, batchId) };
11163
+ } catch (error) {
11164
+ return lesefehler(`Batch ${batchId} konnte nicht gelesen werden`, error);
11165
+ }
11166
+ },
11167
+ async listOrdersForPromptRun(runId) {
11168
+ try {
11169
+ const events = await channel.readEvents();
11170
+ return { kind: "ok", value: ordersForPromptRun(events, runId) };
11171
+ } catch (error) {
11172
+ return lesefehler(`Bildgenerierungsauftraege fuer Lauf ${runId} konnten nicht gelesen werden`, error);
11173
+ }
11174
+ }
11175
+ };
11176
+ }
11177
+
11178
+ // src/lib/szenen/hfImageBatchPersistence.ts
11179
+ function fehler3(nachricht, retryable = true) {
11180
+ return { kind: "error", message: nachricht, retryable };
11181
+ }
11182
+ async function legeBatchAb(options, input) {
11183
+ const { namespace, token, channel } = options;
11184
+ const newImageId = options.newImageId ?? ((batchId, position) => `${batchId}-${position}`);
11185
+ const now = options.now ?? (() => /* @__PURE__ */ new Date());
11186
+ const itemId = itemIdForRun(input.runId);
11187
+ let vorhandeneEvents;
11188
+ try {
11189
+ vorhandeneEvents = await channel.readEvents();
11190
+ } catch (error) {
11191
+ return fehler3(
11192
+ `Bild-Batches von Lauf ${input.runId} konnten vor dem Ablegen nicht gelesen werden: ${error instanceof Error ? error.message : String(error)}`
11193
+ );
11194
+ }
11195
+ const bestehend = batchesForPromptRun(vorhandeneEvents, input.runId)[0] ?? null;
11196
+ if (bestehend?.generation_batch_ids.includes(input.generationBatchId)) {
11197
+ return { kind: "ok", value: bestehend };
11198
+ }
11199
+ const startPosition = bestehend?.images.length ?? 0;
11200
+ const abgelegt = [];
11201
+ for (let offset = 0; offset < input.images.length; offset++) {
11202
+ const bild = input.images[offset];
11203
+ const id = newImageId(input.generationBatchId, startPosition + offset);
11204
+ try {
11205
+ await hfUploadImage(bild.imageBase64, id, token, bild.mimeType);
11206
+ await writeHFEvent(namespace, token, "image_added", {
11207
+ id,
11208
+ prompt: input.title ?? `Batch ${input.generationBatchId}`,
11209
+ tags: [],
11210
+ timestamp: now().getTime(),
11211
+ mimeType: bild.mimeType
11212
+ }, []);
11213
+ } catch (error) {
11214
+ return fehler3(
11215
+ `Bild ${offset + 1}/${input.images.length} des Batches ${input.generationBatchId} konnte nicht im Bildbestand abgelegt werden: ${error instanceof Error ? error.message : String(error)}. Bereits abgelegte Bilder dieses Versuchs (${abgelegt.length}) bleiben im Bestand, geh\xF6ren aber zu keinem Batch, solange das Batch-Ereignis nicht geschrieben ist.`
11216
+ );
11217
+ }
11218
+ abgelegt.push({
11219
+ position: startPosition + offset,
11220
+ media_ref: id,
11221
+ asset_id: id,
11222
+ model: bild.model ?? null,
11223
+ seed: bild.seed ?? null,
11224
+ width: bild.width ?? null,
11225
+ height: bild.height ?? null
11226
+ });
11227
+ }
11228
+ const titel = bestehend?.title ?? (input.title?.trim() || `Batch aus Lauf ${input.runId}`);
11229
+ const payload = {
11230
+ item_id: itemId,
11231
+ prompt_run_id: input.runId,
11232
+ generation_batch_id: input.generationBatchId,
11233
+ source_kind: input.sourceKind,
11234
+ title: titel,
11235
+ images: abgelegt,
11236
+ created_at: now().toISOString()
11237
+ };
11238
+ try {
11239
+ await channel.appendEvent(SZENEN_EVENT_TYPES.imageBatchPersisted, payload);
11240
+ } catch (error) {
11241
+ return fehler3(
11242
+ `Die Batch-Metadaten fuer ${input.generationBatchId} konnten nicht protokolliert werden, obwohl die Bilder bereits im Bestand liegen: ${error instanceof Error ? error.message : String(error)}`
11243
+ );
11244
+ }
11245
+ const zusammengefuehrt = {
11246
+ item_id: itemId,
11247
+ prompt_run_id: input.runId,
11248
+ generation_batch_ids: bestehend ? [...bestehend.generation_batch_ids, input.generationBatchId] : [input.generationBatchId],
11249
+ source_kind: bestehend?.source_kind ?? input.sourceKind,
11250
+ title: titel,
11251
+ images: [...bestehend?.images ?? [], ...abgelegt]
11252
+ };
11253
+ return { kind: "ok", value: zusammengefuehrt };
11254
+ }
11255
+ function createHfImageGenerationBatchPersistence(options) {
11256
+ return {
11257
+ async persist(input) {
11258
+ return legeBatchAb(options, {
11259
+ runId: input.runId,
11260
+ generationBatchId: input.generationBatchId,
11261
+ sourceKind: "generated_in_app",
11262
+ images: input.images.map((bild) => ({
11263
+ imageBase64: bild.imageBase64,
11264
+ // Flow liefert PNG-Base64 (bestehende Konvention, s. AvatarArchitectApp.tsx
11265
+ // `data:image/png;base64,${base64}`); der gemeinsame Vertrag führt
11266
+ // keinen MIME-Typ je Bild.
11267
+ mimeType: "image/png",
11268
+ model: bild.model ?? null,
11269
+ seed: bild.seed ?? null,
11270
+ width: bild.width ?? null,
11271
+ height: bild.height ?? null
11272
+ }))
11273
+ });
11274
+ }
11275
+ };
11276
+ }
11277
+ function createHfImageBatchWrite(options) {
11278
+ return {
11279
+ async importBatch(input) {
11280
+ return legeBatchAb(options, {
11281
+ runId: input.runId,
11282
+ generationBatchId: input.generationBatchId,
11283
+ sourceKind: "external_import",
11284
+ title: input.title,
11285
+ images: input.images.map((bild) => ({
11286
+ imageBase64: bild.imageBase64,
11287
+ mimeType: "image/png",
11288
+ model: bild.model ?? null,
11289
+ seed: bild.seed ?? null,
11290
+ width: bild.width ?? null,
11291
+ height: bild.height ?? null
11292
+ }))
11293
+ });
11294
+ },
11295
+ async attachLibraryItem(input) {
11296
+ let events;
11297
+ try {
11298
+ events = await options.channel.readEvents();
11299
+ } catch (error) {
11300
+ return {
11301
+ kind: "error",
11302
+ message: `Batches konnten nicht gelesen werden: ${error instanceof Error ? error.message : String(error)}`,
11303
+ retryable: true
11304
+ };
11305
+ }
11306
+ const item = collectImageBatches(events).find((b) => b.item_id === input.itemId);
11307
+ if (!item) {
11308
+ return { kind: "error", message: `Item ${input.itemId} ist unbekannt.`, retryable: false };
11309
+ }
11310
+ if (item.prompt_run_id !== input.runId) {
11311
+ return {
11312
+ kind: "conflict",
11313
+ message: `Item ${input.itemId} geh\xF6rt bereits zu Lauf ${item.prompt_run_id}.`,
11314
+ existingPromptRunId: item.prompt_run_id
11315
+ };
11316
+ }
11317
+ return { kind: "ok", value: item };
11318
+ }
11319
+ };
11320
+ }
11321
+
10999
11322
  // src/lib/szenen/flowViewPort.ts
11000
11323
  var defaultContext = {
11001
11324
  async chainFor(contextId) {
@@ -11043,8 +11366,36 @@ function createFlowSzenenViewPort(options) {
11043
11366
  ...options.newRunId ? { newRunId: options.newRunId } : {},
11044
11367
  ...options.now ? { now: options.now } : {}
11045
11368
  });
11046
- const port = { elements, context, runs, derivation };
11369
+ const imageBatchHistory = createHfImageBatchHistory({ channel });
11370
+ const hatHfZugangsdaten = Boolean(options.namespace?.trim() && options.token?.trim());
11371
+ const imageBatchWrite = hatHfZugangsdaten ? createHfImageBatchWrite({
11372
+ namespace: options.namespace,
11373
+ token: options.token,
11374
+ channel,
11375
+ ...options.newBatchImageId ? { newImageId: options.newBatchImageId } : {},
11376
+ ...options.now ? { now: options.now } : {}
11377
+ }) : void 0;
11378
+ const bildProvider = options.imageProvider ?? (options.generateImage ? createFlowImageProvider(options.generateImage) : void 0);
11379
+ const imageGeneration = bildProvider && imageBatchWrite ? createImageGenerationPort({
11380
+ runs: { async getRun(runId) {
11381
+ return runs.getRun(runId);
11382
+ } },
11383
+ provider: bildProvider,
11384
+ batches: createHfImageGenerationBatchPersistence({
11385
+ namespace: options.namespace,
11386
+ token: options.token,
11387
+ channel,
11388
+ ...options.newBatchImageId ? { newImageId: options.newBatchImageId } : {},
11389
+ ...options.now ? { now: options.now } : {}
11390
+ }),
11391
+ events: channel,
11392
+ hasAccess: options.imageProviderHasAccess ?? flowImageProviderHasAccess,
11393
+ ...options.now ? { now: options.now } : {}
11394
+ }) : void 0;
11395
+ const port = { elements, context, runs, derivation, imageBatchHistory };
11047
11396
  if (imageLibrary) port.imageLibrary = imageLibrary;
11397
+ if (imageBatchWrite) port.imageBatchWrite = imageBatchWrite;
11398
+ if (imageGeneration) port.imageGeneration = imageGeneration;
11048
11399
  return port;
11049
11400
  }
11050
11401
 
@@ -11172,7 +11523,7 @@ var PFLICHTFELDER = [
11172
11523
  "system_prompt",
11173
11524
  "created_at"
11174
11525
  ];
11175
- function istText4(wert) {
11526
+ function istText5(wert) {
11176
11527
  return typeof wert === "string" && wert.trim().length > 0;
11177
11528
  }
11178
11529
  function isObject10(wert) {
@@ -11186,7 +11537,7 @@ function pruefeLaufherkunft(quelle) {
11186
11537
  }
11187
11538
  if (quelle.kind === "published") {
11188
11539
  for (const feld of VERSIONSFELDER) {
11189
- if (!istText4(quelle[feld])) {
11540
+ if (!istText5(quelle[feld])) {
11190
11541
  return { ok: false, message: `"source.${feld}" fehlt oder ist leer.` };
11191
11542
  }
11192
11543
  }
@@ -11198,7 +11549,7 @@ function pruefeLaufherkunft(quelle) {
11198
11549
  message: `"source.kind" ist unbekannt: ${JSON.stringify(quelle.kind)}. Erlaubt: published, draft_chain.`
11199
11550
  };
11200
11551
  }
11201
- if (!istText4(quelle.chain_id)) {
11552
+ if (!istText5(quelle.chain_id)) {
11202
11553
  return { ok: false, message: '"source.chain_id" fehlt oder ist leer.' };
11203
11554
  }
11204
11555
  if (!Array.isArray(quelle.nodes) || quelle.nodes.length === 0) {
@@ -11217,7 +11568,7 @@ function pruefeLaufherkunft(quelle) {
11217
11568
  message: `"source.nodes[${index}].type" ist unbekannt: ${JSON.stringify(knoten.type)}.`
11218
11569
  };
11219
11570
  }
11220
- if (!istText4(knoten.element_id) || !istText4(knoten.draft_id)) {
11571
+ if (!istText5(knoten.element_id) || !istText5(knoten.draft_id)) {
11221
11572
  return {
11222
11573
  ok: false,
11223
11574
  message: `"source.nodes[${index}]" braucht element_id und draft_id.`
@@ -11230,10 +11581,10 @@ function pruefeLaufherkunft(quelle) {
11230
11581
  };
11231
11582
  }
11232
11583
  }
11233
- if (quelle.derivation_run_id !== void 0 && !istText4(quelle.derivation_run_id)) {
11584
+ if (quelle.derivation_run_id !== void 0 && !istText5(quelle.derivation_run_id)) {
11234
11585
  return { ok: false, message: '"source.derivation_run_id" ist gesetzt, aber leer.' };
11235
11586
  }
11236
- if (quelle.derivation_recovery_id !== void 0 && !istText4(quelle.derivation_recovery_id)) {
11587
+ if (quelle.derivation_recovery_id !== void 0 && !istText5(quelle.derivation_recovery_id)) {
11237
11588
  return { ok: false, message: '"source.derivation_recovery_id" ist gesetzt, aber leer.' };
11238
11589
  }
11239
11590
  return { ok: true };
@@ -11254,13 +11605,13 @@ function checkPromptRunRecord(candidate) {
11254
11605
  }
11255
11606
  const pflicht = ausKette ? PFLICHTFELDER.filter((f) => !VERSIONSFELDER.includes(f)) : PFLICHTFELDER;
11256
11607
  for (const feld of pflicht) {
11257
- if (!istText4(record[feld])) {
11608
+ if (!istText5(record[feld])) {
11258
11609
  return { ok: false, message: `"${feld}" fehlt oder ist leer.` };
11259
11610
  }
11260
11611
  }
11261
11612
  if (ausKette) {
11262
11613
  for (const feld of VERSIONSFELDER) {
11263
- if (istText4(record[feld])) {
11614
+ if (istText5(record[feld])) {
11264
11615
  return {
11265
11616
  ok: false,
11266
11617
  message: `"${feld}" ist bei einem Lauf aus einer Draft-Kette gesetzt. Dort gibt es keine Versionen, und erfundene sind unzulaessig (D-98).`
@@ -11298,7 +11649,7 @@ function checkPromptRunRecord(candidate) {
11298
11649
  message: `"failure.class" ist unbekannt: ${JSON.stringify(failure.class)}. Erlaubt sind ${FAILURE_CLASSES.join(", ")}.`
11299
11650
  };
11300
11651
  }
11301
- if (!istText4(failure.message)) {
11652
+ if (!istText5(failure.message)) {
11302
11653
  return { ok: false, message: '"failure.message" fehlt oder ist leer.' };
11303
11654
  }
11304
11655
  return { ok: true };
@@ -11340,7 +11691,7 @@ function checkSceneDerivationRecord(candidate) {
11340
11691
  }
11341
11692
  const record = candidate;
11342
11693
  for (const feld of DERIVATION_PFLICHTFELDER) {
11343
- if (!istText4(record[feld])) {
11694
+ if (!istText5(record[feld])) {
11344
11695
  return { ok: false, message: `"${feld}" fehlt oder ist leer.` };
11345
11696
  }
11346
11697
  }
@@ -11395,13 +11746,13 @@ function checkSceneDerivationRecord(candidate) {
11395
11746
  return { ok: false, message: '"follows" muss ein Objekt sein.' };
11396
11747
  }
11397
11748
  const f = folgt;
11398
- if (!istText4(f.run_id)) {
11749
+ if (!istText5(f.run_id)) {
11399
11750
  return { ok: false, message: '"follows.run_id" fehlt oder ist leer.' };
11400
11751
  }
11401
11752
  if (f.run_id === record.run_id) {
11402
11753
  return { ok: false, message: '"follows.run_id" zeigt auf den Lauf selbst.' };
11403
11754
  }
11404
- if (!istText4(f.note)) {
11755
+ if (!istText5(f.note)) {
11405
11756
  return {
11406
11757
  ok: false,
11407
11758
  message: '"follows.note" fehlt oder ist leer \u2014 ohne Beanstandung ist ein Folgelauf nicht nachvollziehbar (D-89).'
@@ -11415,7 +11766,7 @@ function checkSceneDerivationRecord(candidate) {
11415
11766
  }
11416
11767
  }
11417
11768
  const reply = record.reply;
11418
- if (reply !== void 0 && !istText4(reply)) {
11769
+ if (reply !== void 0 && !istText5(reply)) {
11419
11770
  return {
11420
11771
  ok: false,
11421
11772
  message: `"reply" ist unbrauchbar: erwartet wird eine nicht leere Zeichenkette, angekommen ist ${JSON.stringify(reply)}. Ohne "reply" einreichen ist zulaessig.`
@@ -11435,7 +11786,7 @@ function checkSceneDerivationRecord(candidate) {
11435
11786
  message: `"failure.class" ist unbekannt: ${JSON.stringify(failure.class)}. Erlaubt sind ${FAILURE_CLASSES.join(", ")}.`
11436
11787
  };
11437
11788
  }
11438
- if (!istText4(failure.message)) {
11789
+ if (!istText5(failure.message)) {
11439
11790
  return { ok: false, message: '"failure.message" fehlt oder ist leer.' };
11440
11791
  }
11441
11792
  if (Array.isArray(record.proposals) && record.proposals.length > 0) {
@@ -11490,7 +11841,7 @@ function checkSceneDerivationRecord(candidate) {
11490
11841
  };
11491
11842
  }
11492
11843
  for (const [gapIndex, luecke] of gaps.entries()) {
11493
- if (!luecke || typeof luecke !== "object" || !istText4(luecke.pointer) || !istText4(luecke.reason)) {
11844
+ if (!luecke || typeof luecke !== "object" || !istText5(luecke.pointer) || !istText5(luecke.reason)) {
11494
11845
  return {
11495
11846
  ok: false,
11496
11847
  message: `"proposals[${index}].gaps[${gapIndex}]" braucht pointer und reason.`
@@ -11516,7 +11867,7 @@ function checkSceneDerivationRecoveryRecord(candidate) {
11516
11867
  }
11517
11868
  const record = candidate;
11518
11869
  for (const feld of ["recovery_id", "run_id", "created_at"]) {
11519
- if (!istText4(record[feld])) {
11870
+ if (!istText5(record[feld])) {
11520
11871
  return { ok: false, message: `"${feld}" fehlt oder ist leer.` };
11521
11872
  }
11522
11873
  }
@@ -11543,7 +11894,7 @@ function checkSceneDerivationRecoveryRecord(candidate) {
11543
11894
  return { ok: false, message: '"diagnostics" muss ein Array sein (auch ein leeres).' };
11544
11895
  }
11545
11896
  for (const [index, befund] of record.diagnostics.entries()) {
11546
- if (!befund || typeof befund !== "object" || !istText4(befund.code) || !istText4(befund.message)) {
11897
+ if (!befund || typeof befund !== "object" || !istText5(befund.code) || !istText5(befund.message)) {
11547
11898
  return {
11548
11899
  ok: false,
11549
11900
  message: `"diagnostics[${index}]" braucht code und message.`
@@ -11595,7 +11946,7 @@ function checkSceneDerivationRecoveryRecord(candidate) {
11595
11946
  }
11596
11947
  if (Array.isArray(gaps)) {
11597
11948
  for (const [gapIndex, luecke] of gaps.entries()) {
11598
- if (!luecke || typeof luecke !== "object" || !istText4(luecke.pointer) || !istText4(luecke.reason)) {
11949
+ if (!luecke || typeof luecke !== "object" || !istText5(luecke.pointer) || !istText5(luecke.reason)) {
11599
11950
  return {
11600
11951
  ok: false,
11601
11952
  message: `"proposals[${index}].gaps[${gapIndex}]" braucht pointer und reason.`
@@ -11692,13 +12043,13 @@ function noticeFor(ergebnis, was) {
11692
12043
  };
11693
12044
  }
11694
12045
  case "rejected": {
11695
- const fehler3 = ergebnis.errors ?? [];
12046
+ const fehler4 = ergebnis.errors ?? [];
11696
12047
  const ungeprueft = ergebnis.unchecked ?? [];
11697
12048
  return {
11698
12049
  tone: "rejected",
11699
- text: `${was}: abgelehnt \u2014 ${fehler3.length} Befund${fehler3.length === 1 ? "" : "e"}.`,
12050
+ text: `${was}: abgelehnt \u2014 ${fehler4.length} Befund${fehler4.length === 1 ? "" : "e"}.`,
11700
12051
  details: [
11701
- ...fehler3.map((f) => `${f.path ?? "(ohne Pfad)"}: ${f.message ?? "ohne Meldung"}`),
12052
+ ...fehler4.map((f) => `${f.path ?? "(ohne Pfad)"}: ${f.message ?? "ohne Meldung"}`),
11702
12053
  // Nicht verschweigen: was nicht geprüft wurde, ist nicht in Ordnung,
11703
12054
  // sondern ungeprüft.
11704
12055
  ...ungeprueft.map((u) => `ungepr\xFCft: ${u}`)
@@ -12204,7 +12555,7 @@ var ERKLAERUNG = {
12204
12555
  };
12205
12556
  var CapabilityPanel = ({ port, elementId, setupPayload }) => {
12206
12557
  const [bericht, setBericht] = (0, import_react4.useState)(null);
12207
- const [fehler3, setFehler] = (0, import_react4.useState)(null);
12558
+ const [fehler4, setFehler] = (0, import_react4.useState)(null);
12208
12559
  (0, import_react4.useEffect)(() => {
12209
12560
  let abgemeldet = false;
12210
12561
  setBericht(null);
@@ -12226,10 +12577,10 @@ var CapabilityPanel = ({ port, elementId, setupPayload }) => {
12226
12577
  abgemeldet = true;
12227
12578
  };
12228
12579
  }, [port, elementId, setupPayload]);
12229
- if (fehler3) {
12580
+ if (fehler4) {
12230
12581
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { "data-testid": "capability-fehler", role: "alert", children: [
12231
12582
  "F\xE4higkeitsbericht nicht erstellbar: ",
12232
- fehler3
12583
+ fehler4
12233
12584
  ] });
12234
12585
  }
12235
12586
  if (!bericht) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { "data-testid": "capability-laden", children: "F\xE4higkeitsbericht wird erstellt \u2026" });
@@ -12731,10 +13082,10 @@ var ZuordnenAktion = ({ port, lauf, onFertig }) => {
12731
13082
  setNotiz(
12732
13083
  ergebnis.kind === "ok" ? { tone: "ok", text: `Importiert als Item ${ergebnis.value.item_id} mit ${bilder.length} Bild(ern).` } : noticeFor(ergebnis, "Externe Bilder importieren")
12733
13084
  );
12734
- } catch (fehler3) {
13085
+ } catch (fehler4) {
12735
13086
  setNotiz({
12736
13087
  tone: "error",
12737
- text: `Externe Bilder importieren: ${fehler3 instanceof Error ? fehler3.message : String(fehler3)}`
13088
+ text: `Externe Bilder importieren: ${fehler4 instanceof Error ? fehler4.message : String(fehler4)}`
12738
13089
  });
12739
13090
  }
12740
13091
  setLaeuft(false);
@@ -14542,6 +14893,7 @@ var SzenenView = ({
14542
14893
  ContractViolation,
14543
14894
  DERIVABLE_TYPES,
14544
14895
  ELEMENT_VERSION_SCHEMA_FILE,
14896
+ FLOW_MODEL_DISPLAY_NAMES,
14545
14897
  PROBE_VERSION_ID,
14546
14898
  REFERENCE_FIELD,
14547
14899
  RULES_WITHOUT_CAPABILITY_EFFECT,
@@ -14561,6 +14913,7 @@ var SzenenView = ({
14561
14913
  VersionDagError,
14562
14914
  areasFor,
14563
14915
  assessDerivationResponse,
14916
+ batchesForPromptRun,
14564
14917
  buildDerivationSystemInstruction,
14565
14918
  buildDerivationUserPrompt,
14566
14919
  buildSystemInstruction,
@@ -14593,6 +14946,7 @@ var SzenenView = ({
14593
14946
  checkSzenenBatchOrigin,
14594
14947
  checkTitle,
14595
14948
  checkWriteDraftInput,
14949
+ collectImageBatches,
14596
14950
  collectImageGenerationOrders,
14597
14951
  collectPromptRuns,
14598
14952
  collectProviderChecks,
@@ -14606,10 +14960,14 @@ var SzenenView = ({
14606
14960
  createEventLogDerivationPersistence,
14607
14961
  createEventLogRunPersistence,
14608
14962
  createFakeTextGenerationPort,
14963
+ createFlowImageProvider,
14609
14964
  createFlowSzenenViewPort,
14610
14965
  createFlowTextGenerationPort,
14611
14966
  createHfElementStore,
14612
14967
  createHfEventChannel,
14968
+ createHfImageBatchHistory,
14969
+ createHfImageBatchWrite,
14970
+ createHfImageGenerationBatchPersistence,
14613
14971
  createHfImageLibrary,
14614
14972
  createImageGenerationPort,
14615
14973
  createInMemoryEventChannel,
@@ -14623,12 +14981,14 @@ var SzenenView = ({
14623
14981
  differentialSteps,
14624
14982
  draftRevisionOf,
14625
14983
  elementStoreContractChecks,
14984
+ findImageBatch,
14626
14985
  findImageGenerationOrder,
14627
14986
  findPromptRun,
14628
14987
  findProviderCheck,
14629
14988
  findSceneDerivation,
14630
14989
  findSceneDerivationRecovery,
14631
14990
  firstError,
14991
+ flowImageProviderHasAccess,
14632
14992
  formatSchemaErrors,
14633
14993
  freezeDraftChain,
14634
14994
  getSzenenSchemas,