@rslsp1/fa-app-tools 3.0.0 → 5.0.0

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.
@@ -39,90 +39,6 @@ async function callOptional(capability, operation) {
39
39
  return operation();
40
40
  }
41
41
 
42
- // src/features/szenen/szenenViewModel.ts
43
- var ALLE_BEREICHE = [
44
- {
45
- id: "derive",
46
- title: "0 \xB7 Rekonstruktion",
47
- description: "Aus einem Bild oder Prompt einen Szenenentwurf vorschlagen lassen."
48
- },
49
- {
50
- id: "elements",
51
- title: "1 \xB7 Bausteine",
52
- description: "Figuren, Orte, Stile und Regeln f\xFCr sp\xE4tere Bildprompts pflegen."
53
- },
54
- {
55
- id: "scene",
56
- title: "2 \xB7 Szene",
57
- description: "Aus Bausteinen eine konkrete Szene und ihre Beziehungen bauen."
58
- },
59
- {
60
- id: "setup",
61
- title: "3 \xB7 Bildaufbau",
62
- description: "Stil, Komposition und Kamera f\xFCr das sp\xE4tere Bild festlegen."
63
- },
64
- {
65
- id: "shot",
66
- title: "4 \xB7 Prompt",
67
- description: "Bildprompt erzeugen, Varianten vergleichen und als Item speichern."
68
- },
69
- {
70
- id: "media",
71
- title: "Referenzen",
72
- description: "Referenzmedien einer Elementversion ansehen und zuordnen."
73
- }
74
- ];
75
- function areasFor(port) {
76
- const faehig = capabilitiesOf(port);
77
- return ALLE_BEREICHE.filter((bereich) => {
78
- if (bereich.id === "media") return faehig.media;
79
- if (bereich.id === "derive") return faehig.derivation;
80
- return true;
81
- });
82
- }
83
- function resolveArea(port, gewuenscht) {
84
- const verfuegbar = areasFor(port);
85
- if (gewuenscht && verfuegbar.some((b) => b.id === gewuenscht)) return gewuenscht;
86
- return verfuegbar.find((b) => b.id === "elements")?.id ?? verfuegbar[0].id;
87
- }
88
- function noticeFor(ergebnis, was) {
89
- switch (ergebnis.kind) {
90
- case "ok":
91
- return { tone: "ok", text: `${was}: erledigt.` };
92
- case "conflict": {
93
- const aktuell = ergebnis.actualRevision;
94
- return {
95
- tone: "conflict",
96
- text: `${was}: inzwischen von anderer Seite ge\xE4ndert` + (aktuell !== void 0 ? ` (aktueller Stand: Revision ${String(aktuell)})` : "") + ". Bitte neu laden und erneut versuchen."
97
- };
98
- }
99
- case "rejected": {
100
- const fehler4 = ergebnis.errors ?? [];
101
- const ungeprueft = ergebnis.unchecked ?? [];
102
- return {
103
- tone: "rejected",
104
- text: `${was}: abgelehnt \u2014 ${fehler4.length} Befund${fehler4.length === 1 ? "" : "e"}.`,
105
- details: [
106
- ...fehler4.map((f) => `${f.path ?? "(ohne Pfad)"}: ${f.message ?? "ohne Meldung"}`),
107
- // Nicht verschweigen: was nicht geprüft wurde, ist nicht in Ordnung,
108
- // sondern ungeprüft.
109
- ...ungeprueft.map((u) => `ungepr\xFCft: ${u}`)
110
- ]
111
- };
112
- }
113
- case "unsupported":
114
- return {
115
- tone: "unsupported",
116
- text: `${was}: von diesem Host nicht angeboten (${String(ergebnis.capability ?? was)}). Das ist kein Fehler und kein vor\xFCbergehender Zustand.`
117
- };
118
- default:
119
- return {
120
- tone: "error",
121
- text: `${was}: ${String(ergebnis.message ?? "unbekannter Fehler")}`
122
- };
123
- }
124
- }
125
-
126
42
  // src/lib/szenen/jsonSchema.ts
127
43
  var SUPPORTED_KEYWORDS = /* @__PURE__ */ new Set([
128
44
  "$ref",
@@ -3196,6 +3112,96 @@ function formatSchemaErrors(errors) {
3196
3112
  return errors.map((e) => `${e.instancePath || "/"} ${e.message}`).join("; ");
3197
3113
  }
3198
3114
 
3115
+ // src/features/szenen/szenenViewModel.ts
3116
+ var KEINE_BAUSTEINE = [
3117
+ "scene",
3118
+ "scene_setup",
3119
+ "shot"
3120
+ ];
3121
+ var BAUSTEIN_TYPES = SZENEN_ELEMENT_TYPES.filter((typ) => !KEINE_BAUSTEINE.includes(typ));
3122
+ var ALLE_BEREICHE = [
3123
+ {
3124
+ id: "derive",
3125
+ title: "0 \xB7 Rekonstruktion",
3126
+ description: "Aus einem Bild oder Prompt einen Szenenentwurf vorschlagen lassen."
3127
+ },
3128
+ {
3129
+ id: "elements",
3130
+ title: "1 \xB7 Bausteine",
3131
+ description: "Figuren, Orte, Stile und Regeln f\xFCr sp\xE4tere Bildprompts pflegen."
3132
+ },
3133
+ {
3134
+ id: "scene",
3135
+ title: "2 \xB7 Szene",
3136
+ description: "Aus Bausteinen eine konkrete Szene und ihre Beziehungen bauen."
3137
+ },
3138
+ {
3139
+ id: "setup",
3140
+ title: "3 \xB7 Bildaufbau",
3141
+ description: "Stil, Komposition und Kamera f\xFCr das sp\xE4tere Bild festlegen."
3142
+ },
3143
+ {
3144
+ id: "shot",
3145
+ title: "4 \xB7 Prompt",
3146
+ description: "Bildprompt erzeugen, Varianten vergleichen und als Item speichern."
3147
+ },
3148
+ {
3149
+ id: "media",
3150
+ title: "Referenzen",
3151
+ description: "Referenzmedien einer Elementversion ansehen und zuordnen."
3152
+ }
3153
+ ];
3154
+ function areasFor(port) {
3155
+ const faehig = capabilitiesOf(port);
3156
+ return ALLE_BEREICHE.filter((bereich) => {
3157
+ if (bereich.id === "media") return faehig.media;
3158
+ if (bereich.id === "derive") return faehig.derivation;
3159
+ return true;
3160
+ });
3161
+ }
3162
+ function resolveArea(port, gewuenscht) {
3163
+ const verfuegbar = areasFor(port);
3164
+ if (gewuenscht && verfuegbar.some((b) => b.id === gewuenscht)) return gewuenscht;
3165
+ return verfuegbar.find((b) => b.id === "elements")?.id ?? verfuegbar[0].id;
3166
+ }
3167
+ function noticeFor(ergebnis, was) {
3168
+ switch (ergebnis.kind) {
3169
+ case "ok":
3170
+ return { tone: "ok", text: `${was}: erledigt.` };
3171
+ case "conflict": {
3172
+ const aktuell = ergebnis.actualRevision;
3173
+ return {
3174
+ tone: "conflict",
3175
+ text: `${was}: inzwischen von anderer Seite ge\xE4ndert` + (aktuell !== void 0 ? ` (aktueller Stand: Revision ${String(aktuell)})` : "") + ". Bitte neu laden und erneut versuchen."
3176
+ };
3177
+ }
3178
+ case "rejected": {
3179
+ const fehler4 = ergebnis.errors ?? [];
3180
+ const ungeprueft = ergebnis.unchecked ?? [];
3181
+ return {
3182
+ tone: "rejected",
3183
+ text: `${was}: abgelehnt \u2014 ${fehler4.length} Befund${fehler4.length === 1 ? "" : "e"}.`,
3184
+ details: [
3185
+ ...fehler4.map((f) => `${f.path ?? "(ohne Pfad)"}: ${f.message ?? "ohne Meldung"}`),
3186
+ // Nicht verschweigen: was nicht geprüft wurde, ist nicht in Ordnung,
3187
+ // sondern ungeprüft.
3188
+ ...ungeprueft.map((u) => `ungepr\xFCft: ${u}`)
3189
+ ]
3190
+ };
3191
+ }
3192
+ case "unsupported":
3193
+ return {
3194
+ tone: "unsupported",
3195
+ text: `${was}: von diesem Host nicht angeboten (${String(ergebnis.capability ?? was)}). Das ist kein Fehler und kein vor\xFCbergehender Zustand.`
3196
+ };
3197
+ default:
3198
+ return {
3199
+ tone: "error",
3200
+ text: `${was}: ${String(ergebnis.message ?? "unbekannter Fehler")}`
3201
+ };
3202
+ }
3203
+ }
3204
+
3199
3205
  // src/lib/szenen/contextVisibility.ts
3200
3206
  var isObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
3201
3207
  function zerlegeKette(contextChain) {
@@ -3378,6 +3384,22 @@ function checkImageExecutionProfile(profile) {
3378
3384
  }
3379
3385
  return befunde;
3380
3386
  }
3387
+ function checkImageExecutionProfiles(profiles) {
3388
+ const anzahlJeKennung = /* @__PURE__ */ new Map();
3389
+ for (const profil of profiles ?? []) {
3390
+ if (!isObject3(profil) || !istText(profil.profile_id)) continue;
3391
+ anzahlJeKennung.set(profil.profile_id, (anzahlJeKennung.get(profil.profile_id) ?? 0) + 1);
3392
+ }
3393
+ return (profiles ?? []).map((profil) => {
3394
+ const befunde = [...checkImageExecutionProfile(profil)];
3395
+ if (isObject3(profil) && istText(profil.profile_id) && (anzahlJeKennung.get(profil.profile_id) ?? 0) > 1) {
3396
+ befunde.push(
3397
+ `Die profile_id "${profil.profile_id}" kommt in diesem Zielmodell mehrfach vor \u2014 die Auswahl waere nicht mehr eindeutig aufloesbar.`
3398
+ );
3399
+ }
3400
+ return befunde;
3401
+ });
3402
+ }
3381
3403
  function executableImageModels(promptTargetModelKey, targets, capability) {
3382
3404
  const models = [];
3383
3405
  const invalid = [];
@@ -3391,8 +3413,9 @@ function executableImageModels(promptTargetModelKey, targets, capability) {
3391
3413
  };
3392
3414
  }
3393
3415
  for (const target of targets ?? []) {
3394
- for (const roh of target.executionProfiles ?? []) {
3395
- const befunde = checkImageExecutionProfile(roh);
3416
+ const profilBefunde = checkImageExecutionProfiles(target.executionProfiles ?? []);
3417
+ for (const [index, roh] of (target.executionProfiles ?? []).entries()) {
3418
+ const befunde = profilBefunde[index] ?? [];
3396
3419
  if (befunde.length > 0) {
3397
3420
  const kennung = isObject3(roh) && istText(roh.profile_id) ? roh.profile_id : "(ohne profile_id)";
3398
3421
  invalid.push(`${target.key}/${kennung}: ${befunde.join(" ")}`);
@@ -3401,13 +3424,20 @@ function executableImageModels(promptTargetModelKey, targets, capability) {
3401
3424
  const profil = roh;
3402
3425
  if (!profil.enabled) continue;
3403
3426
  if (!profil.environments.includes(capability.environment_id)) continue;
3404
- if (!capability.execution_paths.includes(profil.execution_path)) continue;
3427
+ const weg = capability.execution_paths.find((r) => r.execution_path === profil.execution_path);
3428
+ if (!weg) continue;
3429
+ if (target.provider !== weg.provider) {
3430
+ invalid.push(
3431
+ `${target.key}/${profil.profile_id}: Das Zielmodell nennt den Anbieter ${target.provider === null ? "(keinen)" : `"${target.provider}"`}, der Aufrufweg "${weg.execution_path}" fuehrt aber zu "${weg.provider}".`
3432
+ );
3433
+ continue;
3434
+ }
3405
3435
  models.push({
3406
3436
  selection_id: `${target.key}#${profil.profile_id}`,
3407
3437
  target_model_key: target.key,
3408
3438
  ...target.versionId ? { target_model_version_id: target.versionId } : {},
3409
3439
  display_name: target.title,
3410
- provider: target.provider ?? "(ohne provider)",
3440
+ provider: weg.provider,
3411
3441
  profile_id: profil.profile_id,
3412
3442
  environment_id: capability.environment_id,
3413
3443
  execution_path: profil.execution_path,
@@ -3426,7 +3456,7 @@ function executableImageModels(promptTargetModelKey, targets, capability) {
3426
3456
  models: [],
3427
3457
  default_selection_id: null,
3428
3458
  invalid_profiles: invalid,
3429
- reason: `In dieser Umgebung (${capability.environment_id}) traegt kein sichtbares Zielmodell ein aktives Ausfuehrungsprofil fuer einen Aufrufweg dieses Hosts (${capability.execution_paths.join(", ") || "keiner"}).`
3459
+ reason: `In dieser Umgebung (${capability.environment_id}) traegt kein sichtbares Zielmodell ein aktives Ausfuehrungsprofil fuer einen Aufrufweg dieses Hosts (${capability.execution_paths.map((r) => r.execution_path).join(", ") || "keiner"}).`
3430
3460
  };
3431
3461
  }
3432
3462
  const passend = models.find((m) => m.is_prompt_target);
@@ -4260,6 +4290,96 @@ function finish(report) {
4260
4290
  };
4261
4291
  }
4262
4292
 
4293
+ // src/lib/szenen/promptOperation.ts
4294
+ var PROMPT_RULE_EFFECT = {
4295
+ "P-01": "diagnostic",
4296
+ // Kamera-ID im Rig nicht auflösbar → ohne Kamera weiter
4297
+ "P-02": "diagnostic",
4298
+ // mehrdeutige Kamera-ID → erklären, nicht sperren
4299
+ "P-03": "diagnostic",
4300
+ // Abstammungsintegrität einer camera_id — Publish-Frage
4301
+ "P-04": "diagnostic",
4302
+ // referenzierte Version nicht veröffentlicht/sichtbar
4303
+ "P-05": "diagnostic",
4304
+ // Node-Referenz nicht auflösbar → Teil auslassen
4305
+ "P-06": "diagnostic",
4306
+ // Placement-Node mehrdeutig → ohne exakte Platzierung
4307
+ "P-07": "diagnostic",
4308
+ // spatial Pattern ohne can_place → Pattern weglassen
4309
+ "P-08": "diagnostic",
4310
+ // unvollständige Pattern-Bindings
4311
+ "P-09": "not_applicable",
4312
+ // reine Publish-/Prozessregel für sequence
4313
+ "P-10": "diagnostic",
4314
+ // Zyklus: Blocker nur, wenn keine endliche Auflösung bleibt
4315
+ "P-11": "diagnostic",
4316
+ // Override-Disziplin, schon bisher advisory
4317
+ "P-12": "not_applicable",
4318
+ // Laufzeitregel der Auflösung, keine Bedingung
4319
+ "P-13": "diagnostic",
4320
+ // pattern_derived ohne Pattern-Platzierung
4321
+ "P-14": "diagnostic",
4322
+ // Bildgrößen-/Optik-Plausibilität, erklärte Absicht gewinnt
4323
+ "P-15": "diagnostic",
4324
+ // vertikaler look_at ohne up_hint — Rollwinkel ist Spezialpräzision
4325
+ "P-16": "diagnostic",
4326
+ // Placements ohne Koordinatensystem
4327
+ "P-17": "diagnostic"
4328
+ // Target Model nicht auflösbar → generischer Prompt
4329
+ };
4330
+ function rulesWithoutPromptEffect(alleRegeln) {
4331
+ return alleRegeln.filter((rule) => !(rule in PROMPT_RULE_EFFECT));
4332
+ }
4333
+ function diagnosticOfFinding(finding) {
4334
+ return {
4335
+ code: finding.rule,
4336
+ origin: "rule",
4337
+ path: finding.path,
4338
+ message: finding.message
4339
+ };
4340
+ }
4341
+ function diagnosticOfSchemaError(error, where) {
4342
+ return {
4343
+ code: "schema",
4344
+ origin: "schema",
4345
+ path: error.instancePath || "/",
4346
+ message: `${where}: ${error.message}`
4347
+ };
4348
+ }
4349
+ function promptDiagnosticsOf(checks) {
4350
+ const befunde = [];
4351
+ for (const finding of checks.findings) {
4352
+ if (PROMPT_RULE_EFFECT[finding.rule] === "not_applicable") continue;
4353
+ befunde.push(diagnosticOfFinding(finding));
4354
+ }
4355
+ return befunde;
4356
+ }
4357
+ var isObject7 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4358
+ var asArray2 = (v) => Array.isArray(v) ? v : [];
4359
+ var istText2 = (v) => typeof v === "string" && v.trim().length > 0;
4360
+ function describableContent(scenePayload) {
4361
+ if (!isObject7(scenePayload)) {
4362
+ return {
4363
+ ok: false,
4364
+ message: `Die Szene ist kein Objekt, sondern ${Array.isArray(scenePayload) ? "ein Array" : typeof scenePayload}. Daraus laesst sich kein Textauftrag herstellen.`
4365
+ };
4366
+ }
4367
+ const nodes = asArray2(scenePayload.nodes);
4368
+ for (const node of nodes) {
4369
+ if (!isObject7(node)) continue;
4370
+ const semantic = isObject7(node.semantic) ? node.semantic : null;
4371
+ if (semantic && istText2(semantic.description)) return { ok: true };
4372
+ if (asArray2(node.component_refs).length > 0) return { ok: true };
4373
+ }
4374
+ const environment = isObject7(scenePayload.environment) ? scenePayload.environment : null;
4375
+ if (environment && istText2(environment.text)) return { ok: true };
4376
+ if (environment && asArray2(environment.component_refs).length > 0) return { ok: true };
4377
+ return {
4378
+ ok: false,
4379
+ message: nodes.length === 0 ? "Die Szene hat keine Knoten und keinen Umgebungstext. Ohne beschreibbaren Inhalt gibt es nichts, woraus ein Prompt entstehen koennte." : `Keiner der ${nodes.length} Knoten traegt eine Beschreibung oder eine Komponentenreferenz, und es gibt keinen Umgebungstext. Ein Prompt daraus waere eine leere Behauptung.`
4380
+ };
4381
+ }
4382
+
4263
4383
  // src/lib/szenen/capabilities.ts
4264
4384
  var CapabilityAnchorError = class extends Error {
4265
4385
  };
@@ -4302,9 +4422,9 @@ var FLAG_OF_SCOPE = {
4302
4422
  // die Vererbung an die beiden anderen weitergereicht.
4303
4423
  global: "can_describe_scene"
4304
4424
  };
4305
- var isObject7 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4425
+ var isObject8 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
4306
4426
  function nodeCountOf(scenePayload) {
4307
- if (!isObject7(scenePayload)) return 0;
4427
+ if (!isObject8(scenePayload)) return 0;
4308
4428
  return Array.isArray(scenePayload.nodes) ? scenePayload.nodes.length : 0;
4309
4429
  }
4310
4430
  async function capabilityReport(input) {
@@ -4329,7 +4449,7 @@ async function capabilityReport(input) {
4329
4449
  reason: "Payload verletzt das Schema \u2014 die Publish-Regeln wurden nicht ausgefuehrt"
4330
4450
  }))
4331
4451
  } : await runPublishChecks({ type, payload: setupPayload, elementId, parents, resolver });
4332
- if (!isObject7(setupPayload)) {
4452
+ if (!isObject8(setupPayload)) {
4333
4453
  const vorgefunden = Array.isArray(setupPayload) ? "array" : typeof setupPayload;
4334
4454
  const reasons = [
4335
4455
  {
@@ -4339,10 +4459,14 @@ async function capabilityReport(input) {
4339
4459
  ];
4340
4460
  return {
4341
4461
  can_describe_scene: { state: "no", reasons },
4462
+ // Auch fuer den Promptpfad ein echter Blocker: Eine Payload, die kein
4463
+ // Objekt ist, ist technisch unlesbar (Schritt 07, Klasse A/C) — nicht
4464
+ // bloss fachlich unvollstaendig.
4342
4465
  can_render_prompt: { state: "no", reasons },
4343
4466
  can_place: { state: "no", reasons },
4344
4467
  checks,
4345
- schemaErrors
4468
+ schemaErrors,
4469
+ promptDiagnostics: []
4346
4470
  };
4347
4471
  }
4348
4472
  const blockedByScope = /* @__PURE__ */ new Map();
@@ -4378,6 +4502,8 @@ async function capabilityReport(input) {
4378
4502
  };
4379
4503
  const base = forFlag("can_describe_scene");
4380
4504
  let describe;
4505
+ let szenenPayload = null;
4506
+ let sceneVersionId = null;
4381
4507
  if (base.blocked.length > 0) {
4382
4508
  describe = { state: "no", reasons: base.blocked };
4383
4509
  } else if (schemaErrors.length > 0) {
@@ -4403,9 +4529,10 @@ async function capabilityReport(input) {
4403
4529
  ]
4404
4530
  };
4405
4531
  } else {
4406
- const sceneRef = isObject7(setupPayload.scene_ref) ? setupPayload.scene_ref : null;
4407
- const sceneVersionId = typeof sceneRef?.version_id === "string" ? sceneRef.version_id : null;
4532
+ const sceneRef = isObject8(setupPayload.scene_ref) ? setupPayload.scene_ref : null;
4533
+ sceneVersionId = typeof sceneRef?.version_id === "string" ? sceneRef.version_id : null;
4408
4534
  const scene = chainScene !== void 0 ? { payload: chainScene } : sceneVersionId ? await resolver.getVersion(sceneVersionId) : null;
4535
+ if (scene) szenenPayload = { payload: scene.payload };
4409
4536
  const nodes = nodeCountOf(scene?.payload);
4410
4537
  if (nodes === 0) {
4411
4538
  describe = {
@@ -4452,15 +4579,38 @@ async function capabilityReport(input) {
4452
4579
  if (own.unchecked.length > 0) return { state: "unknown", reasons: own.unchecked };
4453
4580
  return { state: "yes", reasons: [] };
4454
4581
  };
4582
+ const promptFlag = (() => {
4583
+ if (!szenenPayload) {
4584
+ return {
4585
+ state: "unknown",
4586
+ reasons: [
4587
+ {
4588
+ kind: "structure",
4589
+ message: `Die Szene ${sceneVersionId ?? "(ohne version_id)"} wurde nicht gelesen; ob beschreibbarer Inhalt vorliegt, ist damit offen \u2014 keine Absage.`
4590
+ }
4591
+ ]
4592
+ };
4593
+ }
4594
+ const inhalt = describableContent(szenenPayload.payload);
4595
+ if (!inhalt.ok) {
4596
+ return { state: "no", reasons: [{ kind: "structure", message: inhalt.message }] };
4597
+ }
4598
+ return { state: "yes", reasons: [] };
4599
+ })();
4600
+ const promptDiagnostics = [
4601
+ ...schemaErrors.map((e) => diagnosticOfSchemaError(e, `Scene Setup ${elementId}`)),
4602
+ ...promptDiagnosticsOf(checks)
4603
+ ];
4455
4604
  return {
4456
4605
  can_describe_scene: describe,
4457
- can_render_prompt: derived("can_render_prompt"),
4606
+ can_render_prompt: promptFlag,
4458
4607
  can_place: derived("can_place", {
4459
4608
  ok: hasPlacementCapability(setupPayload),
4460
4609
  message: "Das Scene Setup traegt kein coordinate_system und ist damit nicht platzierbar (D-65)."
4461
4610
  }),
4462
4611
  checks,
4463
- schemaErrors
4612
+ schemaErrors,
4613
+ promptDiagnostics
4464
4614
  };
4465
4615
  }
4466
4616
  function unclassifiedPublishRules() {
@@ -4468,6 +4618,27 @@ function unclassifiedPublishRules() {
4468
4618
  (rule) => !(rule in RULE_SCOPES) && !(rule in RULES_WITHOUT_CAPABILITY_EFFECT)
4469
4619
  );
4470
4620
  }
4621
+ function sceneOnlyCapabilities(scenePayload) {
4622
+ const knoten = nodeCountOf(scenePayload);
4623
+ const inhalt = describableContent(scenePayload);
4624
+ return {
4625
+ can_describe_scene: knoten > 0 ? { state: "yes", reasons: [] } : {
4626
+ state: "no",
4627
+ reasons: [{
4628
+ kind: "structure",
4629
+ message: "Die Szene hat keine Knoten. Ohne Knoten gibt es nichts zu beschreiben."
4630
+ }]
4631
+ },
4632
+ can_render_prompt: inhalt.ok ? { state: "yes", reasons: [] } : { state: "no", reasons: [{ kind: "structure", message: inhalt.message }] },
4633
+ can_place: {
4634
+ state: "no",
4635
+ reasons: [{
4636
+ kind: "structure",
4637
+ message: "Zu dieser Szene gehoert kein Scene Setup. Weltplatzierung und coordinate_system liegen ausschliesslich dort (D-39/D-65) \u2014 es gibt also keine belastbaren Koordinaten."
4638
+ }]
4639
+ }
4640
+ };
4641
+ }
4471
4642
 
4472
4643
  // src/lib/szenen/szenenPorts.ts
4473
4644
  function resolverFromQueries(queries, contexts) {
@@ -4525,13 +4696,13 @@ function isSzenenItemId(itemId) {
4525
4696
  return itemId.startsWith(SZENEN_ITEM_PREFIX);
4526
4697
  }
4527
4698
  function checkSzenenBatchOrigin(candidate) {
4528
- if (!istText2(candidate.prompt_run_id)) {
4699
+ if (!istText3(candidate.prompt_run_id)) {
4529
4700
  return {
4530
4701
  kind: "rejected",
4531
4702
  failure: { field: "prompt_run_id", message: '"prompt_run_id" fehlt oder ist leer.' }
4532
4703
  };
4533
4704
  }
4534
- if (!istText2(candidate.generation_batch_id)) {
4705
+ if (!istText3(candidate.generation_batch_id)) {
4535
4706
  return {
4536
4707
  kind: "rejected",
4537
4708
  failure: {
@@ -4574,7 +4745,7 @@ function mergeSzenenBatchOrigin(bestehend, neu) {
4574
4745
  };
4575
4746
  }
4576
4747
  var DEFAULT_FSK_LEVEL = "FSK16";
4577
- var istText2 = (v) => typeof v === "string" && v.trim().length > 0;
4748
+ var istText3 = (v) => typeof v === "string" && v.trim().length > 0;
4578
4749
  function roundOfRun(run, runsOfShot) {
4579
4750
  return runsOfShot.findIndex((kandidat) => kandidat.run_id === run.run_id) + 1;
4580
4751
  }
@@ -4610,7 +4781,7 @@ function deriveItemFromRun(input) {
4610
4781
  }
4611
4782
  };
4612
4783
  }
4613
- if (!run.output || !istText2(run.output.positive)) {
4784
+ if (!run.output || !istText3(run.output.positive)) {
4614
4785
  return {
4615
4786
  kind: "rejected",
4616
4787
  failure: {
@@ -4631,8 +4802,8 @@ function deriveItemFromRun(input) {
4631
4802
  }
4632
4803
  const item_id = itemIdForRun(run.run_id);
4633
4804
  const lineage = deriveLineage(item_id, round, existingItems);
4634
- const negative = istText2(run.output.negative) ? run.output.negative : null;
4635
- const title = istText2(input.title) ? input.title : istText2(input.shotTitle) ? `${input.shotTitle} \xB7 Runde ${round}` : `Szenen-Lauf ${round}`;
4805
+ const negative = istText3(run.output.negative) ? run.output.negative : null;
4806
+ const title = istText3(input.title) ? input.title : istText3(input.shotTitle) ? `${input.shotTitle} \xB7 Runde ${round}` : `Szenen-Lauf ${round}`;
4636
4807
  return {
4637
4808
  kind: "ok",
4638
4809
  value: {
@@ -4642,9 +4813,9 @@ function deriveItemFromRun(input) {
4642
4813
  negative_prompt: negative,
4643
4814
  // `feedback` ist Pflicht (D-55) und ist genau die Erlaeuterung fuer den
4644
4815
  // Menschen — also gehoert sie in das Feld fuer Notizen.
4645
- notes: istText2(input.notes) ? input.notes : run.output.feedback,
4816
+ notes: istText3(input.notes) ? input.notes : run.output.feedback,
4646
4817
  rating: typeof input.rating === "number" ? input.rating : 0,
4647
- fsk_level: istText2(input.fskLevel) ? input.fskLevel : DEFAULT_FSK_LEVEL,
4818
+ fsk_level: istText3(input.fskLevel) ? input.fskLevel : DEFAULT_FSK_LEVEL,
4648
4819
  tags: [],
4649
4820
  szenen: {
4650
4821
  prompt_run_id: run.run_id,
@@ -5054,6 +5225,29 @@ function findPromptRun(events, runId) {
5054
5225
  return collectPromptRuns(events).find((run) => run.run_id === runId) ?? null;
5055
5226
  }
5056
5227
 
5228
+ // src/lib/szenen/bildVorschau.ts
5229
+ async function ladeVorschauen(port, mediaRefs, fertig, optionen = {}) {
5230
+ const laden = port.loadPreview;
5231
+ if (!laden) return;
5232
+ const parallel = Math.max(1, optionen.parallel ?? 4);
5233
+ const lauf = optionen.lauf;
5234
+ const offen = mediaRefs.filter((ref) => !(optionen.hat?.(ref) ?? false));
5235
+ let naechster = 0;
5236
+ async function arbeiter() {
5237
+ while (naechster < offen.length) {
5238
+ if (lauf?.abgebrochen) return;
5239
+ const ref = offen[naechster];
5240
+ naechster += 1;
5241
+ const ergebnis = await laden.call(port, ref);
5242
+ if (lauf?.abgebrochen) return;
5243
+ if (ergebnis.kind === "ok") fertig(ref, ergebnis.value);
5244
+ }
5245
+ }
5246
+ await Promise.all(
5247
+ Array.from({ length: Math.min(parallel, offen.length) }, () => arbeiter())
5248
+ );
5249
+ }
5250
+
5057
5251
  // src/lib/szenen/textGenerationPort.ts
5058
5252
  function simulatedAnswerFor(request) {
5059
5253
  let input;
@@ -5518,7 +5712,7 @@ function validateDerivationInput(input) {
5518
5712
  if (input.policy.produces.length === 0) return "Die Regel erzeugt keinen einzigen Vorschlag.";
5519
5713
  return null;
5520
5714
  }
5521
- var isObject8 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
5715
+ var isObject9 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
5522
5716
  var MAX_PROPOSAL_TITLE_LENGTH = 120;
5523
5717
  function fallbackProposalTitle(type) {
5524
5718
  return `Rekonstruktion ${type}`;
@@ -5544,7 +5738,7 @@ function resolveJsonPointer(wurzel, pointer) {
5544
5738
  aktuell = aktuell[index];
5545
5739
  continue;
5546
5740
  }
5547
- if (!isObject8(aktuell) || !(schluessel in aktuell)) {
5741
+ if (!isObject9(aktuell) || !(schluessel in aktuell)) {
5548
5742
  return { found: false, value: void 0 };
5549
5743
  }
5550
5744
  aktuell = aktuell[schluessel];
@@ -5558,7 +5752,7 @@ function collectVersionRefs2(value) {
5558
5752
  knoten.forEach(besuchen);
5559
5753
  return;
5560
5754
  }
5561
- if (!isObject8(knoten)) return;
5755
+ if (!isObject9(knoten)) return;
5562
5756
  if (typeof knoten.element_id === "string" && typeof knoten.version_id === "string") {
5563
5757
  gefunden.push({ element_id: knoten.element_id, version_id: knoten.version_id });
5564
5758
  }
@@ -5624,7 +5818,7 @@ function assessDerivationResponse(value, input) {
5624
5818
  envelope: null,
5625
5819
  contract_ok: false
5626
5820
  });
5627
- if (!isObject8(value)) {
5821
+ if (!isObject9(value)) {
5628
5822
  befund({
5629
5823
  code: "response.not_object",
5630
5824
  severity: "error",
@@ -5642,7 +5836,7 @@ function assessDerivationResponse(value, input) {
5642
5836
  });
5643
5837
  }
5644
5838
  const rohProposals = value.proposals;
5645
- const proposalsLesbar = isObject8(rohProposals);
5839
+ const proposalsLesbar = isObject9(rohProposals);
5646
5840
  if (!proposalsLesbar) {
5647
5841
  befund({
5648
5842
  code: "envelope.proposals_missing",
@@ -5652,7 +5846,7 @@ function assessDerivationResponse(value, input) {
5652
5846
  });
5653
5847
  }
5654
5848
  const roh = proposalsLesbar ? rohProposals : {};
5655
- const rohGaps = isObject8(value.gaps) ? value.gaps : {};
5849
+ const rohGaps = isObject9(value.gaps) ? value.gaps : {};
5656
5850
  const gapsUngefragt = Object.keys(rohGaps).filter(
5657
5851
  (t) => !input.policy.produces.includes(t)
5658
5852
  );
@@ -5664,7 +5858,7 @@ function assessDerivationResponse(value, input) {
5664
5858
  pointer: "/gaps"
5665
5859
  });
5666
5860
  }
5667
- const fehlend = input.policy.produces.filter((t) => !isObject8(roh[t]));
5861
+ const fehlend = input.policy.produces.filter((t) => !isObject9(roh[t]));
5668
5862
  if (fehlend.length > 0 && proposalsLesbar) {
5669
5863
  const d = befund({
5670
5864
  code: "envelope.proposals_missing_types",
@@ -5685,10 +5879,10 @@ function assessDerivationResponse(value, input) {
5685
5879
  pointer: "/proposals"
5686
5880
  });
5687
5881
  }
5688
- const rohTitles = isObject8(value.titles) ? value.titles : {};
5882
+ const rohTitles = isObject9(value.titles) ? value.titles : {};
5689
5883
  const umgebucht = [];
5690
5884
  for (const type of input.policy.produces) {
5691
- if (!isObject8(roh[type])) continue;
5885
+ if (!isObject9(roh[type])) continue;
5692
5886
  const payload = roh[type];
5693
5887
  const eigene = [];
5694
5888
  const bezug = REFERENCE_FIELD[type];
@@ -5724,7 +5918,7 @@ function assessDerivationResponse(value, input) {
5724
5918
  const bezugPointer = bezug ? `/${bezug.field}` : null;
5725
5919
  let gapFehler = false;
5726
5920
  for (const eintrag of benannt) {
5727
- if (!isObject8(eintrag) || typeof eintrag.pointer !== "string" || typeof eintrag.reason !== "string" || !eintrag.reason.trim()) {
5921
+ if (!isObject9(eintrag) || typeof eintrag.pointer !== "string" || typeof eintrag.reason !== "string" || !eintrag.reason.trim()) {
5728
5922
  eigene.push(befund({
5729
5923
  code: "proposal.gap_entry_invalid",
5730
5924
  severity: "error",
@@ -5800,7 +5994,7 @@ function assessDerivationResponse(value, input) {
5800
5994
  });
5801
5995
  } else {
5802
5996
  for (const eintrag of value.not_derivable) {
5803
- if (!isObject8(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.reason !== "string") {
5997
+ if (!isObject9(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.reason !== "string") {
5804
5998
  befund({
5805
5999
  code: "envelope.not_derivable_entry_invalid",
5806
6000
  severity: "error",
@@ -5825,7 +6019,7 @@ function assessDerivationResponse(value, input) {
5825
6019
  });
5826
6020
  } else {
5827
6021
  for (const eintrag of value.conflicts) {
5828
- if (!isObject8(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.from_image !== "string" || typeof eintrag.from_prompt !== "string") {
6022
+ if (!isObject9(eintrag) || typeof eintrag.field !== "string" || typeof eintrag.from_image !== "string" || typeof eintrag.from_prompt !== "string") {
5829
6023
  befund({
5830
6024
  code: "envelope.conflicts_entry_invalid",
5831
6025
  severity: "error",
@@ -6012,10 +6206,10 @@ async function runSceneDerivation(input, port, userPrompt) {
6012
6206
  }
6013
6207
 
6014
6208
  // src/features/szenen/SzenenView.tsx
6015
- import { useMemo as useMemo3, useState as useState15 } from "react";
6209
+ import { useMemo as useMemo4, useState as useState16 } from "react";
6016
6210
 
6017
6211
  // src/features/szenen/areas/ElementsArea.tsx
6018
- import { useState as useState10 } from "react";
6212
+ import { useState as useState11 } from "react";
6019
6213
 
6020
6214
  // src/features/szenen/areas/usePortQuery.ts
6021
6215
  import { useEffect, useRef, useState } from "react";
@@ -6049,6 +6243,32 @@ function usePortQuery(frage, abhaengigkeiten) {
6049
6243
  // src/features/szenen/areas/ElementDetail.tsx
6050
6244
  import { useEffect as useEffect3, useMemo as useMemo2, useState as useState9 } from "react";
6051
6245
 
6246
+ // src/features/szenen/elementLabels.ts
6247
+ var LABELS = {
6248
+ scene_component: { singular: "Szenenbaustein", plural: "Szenenbausteine" },
6249
+ scene: { singular: "Szene", plural: "Szenen" },
6250
+ shot_concept: { singular: "Prompt-Idee", plural: "Prompt-Ideen" },
6251
+ camera_preset: { singular: "Kamera", plural: "Kameras" },
6252
+ camera_pattern: { singular: "Kamera-Muster", plural: "Kamera-Muster" },
6253
+ style: { singular: "Stil", plural: "Stile" },
6254
+ scene_setup: { singular: "Bildaufbau", plural: "Bildaufbauten" },
6255
+ shot: { singular: "Prompt", plural: "Prompts" },
6256
+ prompt_policy: { singular: "Prompt-Regel", plural: "Prompt-Regeln" },
6257
+ prompt_fragment: { singular: "Prompt-Baustein", plural: "Prompt-Bausteine" },
6258
+ target_model: { singular: "Zielmodell", plural: "Zielmodelle" },
6259
+ sequence: { singular: "Sequenz", plural: "Sequenzen" },
6260
+ scene_derivation_policy: {
6261
+ singular: "Rekonstruktions-Regel",
6262
+ plural: "Rekonstruktions-Regeln"
6263
+ }
6264
+ };
6265
+ function elementTypLabel(typ) {
6266
+ return LABELS[typ]?.singular ?? typ;
6267
+ }
6268
+ function elementTypPlural(typ) {
6269
+ return LABELS[typ]?.plural ?? typ;
6270
+ }
6271
+
6052
6272
  // src/features/szenen/schemaForm.ts
6053
6273
  var FORM_JE_REF = {
6054
6274
  "common.schema.json#/$defs/slug": "slug",
@@ -6344,7 +6564,7 @@ var SEMANTIK = {
6344
6564
  function feldSemantik(type, pfad) {
6345
6565
  return SEMANTIK[`${type}.${pfad}`] ?? null;
6346
6566
  }
6347
- var LABELS = {
6567
+ var LABELS2 = {
6348
6568
  key: "Kennung",
6349
6569
  name: "Name",
6350
6570
  text: "Text",
@@ -6389,13 +6609,13 @@ var LABELS = {
6389
6609
  properties: "Zusatzangaben"
6390
6610
  };
6391
6611
  function feldLabel(type, pfad, name) {
6392
- return feldSemantik(type, pfad)?.label ?? LABELS[name] ?? name;
6612
+ return feldSemantik(type, pfad)?.label ?? LABELS2[name] ?? name;
6393
6613
  }
6394
6614
 
6395
6615
  // src/features/szenen/areas/SchemaFields.tsx
6396
6616
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
6397
- var isObject9 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
6398
- var istVersionRef = (v) => isObject9(v) && typeof v.element_id === "string" && typeof v.version_id === "string";
6617
+ var isObject10 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
6618
+ var istVersionRef = (v) => isObject10(v) && typeof v.element_id === "string" && typeof v.version_id === "string";
6399
6619
  function leseJson(wert) {
6400
6620
  if (!wert || wert === NULL_MARKER) return null;
6401
6621
  try {
@@ -6623,13 +6843,13 @@ var VersionRefListeFeld = ({ port, kontextkette, feld, wert, onChange, readOnly,
6623
6843
  }
6624
6844
  const schreiben = (neu) => onChange(
6625
6845
  feld.path,
6626
- schreibListe(neu.map((eintrag, i) => isObject9(eintrag) && mitRolle ? { ...eintrag, rank: i } : eintrag))
6846
+ schreibListe(neu.map((eintrag, i) => isObject10(eintrag) && mitRolle ? { ...eintrag, rank: i } : eintrag))
6627
6847
  );
6628
6848
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__reflist", "data-testid": `reflist-${feld.path}`, children: [
6629
6849
  liste.length === 0 && /* @__PURE__ */ jsx("p", { "data-testid": `reflist-${feld.path}-leer`, children: "Keine Eintr\xE4ge." }),
6630
6850
  /* @__PURE__ */ jsx("ol", { children: liste.map((eintrag, index) => /* @__PURE__ */ jsxs("li", { "data-testid": `reflist-${feld.path}-${index}`, children: [
6631
6851
  istVersionRef(eintrag) ? /* @__PURE__ */ jsx(RefAnzeige, { port, ref_: eintrag, testId: `reflist-${feld.path}-${index}-ref` }) : /* @__PURE__ */ jsx("code", { children: JSON.stringify(eintrag) }),
6632
- mitRolle === "styleRole" && isObject9(eintrag) && /* @__PURE__ */ jsxs(
6852
+ mitRolle === "styleRole" && isObject10(eintrag) && /* @__PURE__ */ jsxs(
6633
6853
  "select",
6634
6854
  {
6635
6855
  "data-testid": `reflist-${feld.path}-${index}-role`,
@@ -6642,7 +6862,7 @@ var VersionRefListeFeld = ({ port, kontextkette, feld, wert, onChange, readOnly,
6642
6862
  ]
6643
6863
  }
6644
6864
  ),
6645
- mitRolle === "frei" && isObject9(eintrag) && /* @__PURE__ */ jsx(
6865
+ mitRolle === "frei" && isObject10(eintrag) && /* @__PURE__ */ jsx(
6646
6866
  "input",
6647
6867
  {
6648
6868
  "data-testid": `reflist-${feld.path}-${index}-role`,
@@ -6652,7 +6872,7 @@ var VersionRefListeFeld = ({ port, kontextkette, feld, wert, onChange, readOnly,
6652
6872
  onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...x, role: e.target.value } : x))
6653
6873
  }
6654
6874
  ),
6655
- mitGewicht && isObject9(eintrag) && /* @__PURE__ */ jsx(
6875
+ mitGewicht && isObject10(eintrag) && /* @__PURE__ */ jsx(
6656
6876
  "input",
6657
6877
  {
6658
6878
  "data-testid": `reflist-${feld.path}-${index}-weight`,
@@ -6883,7 +7103,7 @@ var KameraFeld = ({
6883
7103
  if (phase.status !== "ready" || !phase.value) return [];
6884
7104
  const cameras = valueAtPath(phase.value.payload, "camera_rig.cameras");
6885
7105
  if (!Array.isArray(cameras)) return [];
6886
- return cameras.filter(isObject9).map((c) => ({
7106
+ return cameras.filter(isObject10).map((c) => ({
6887
7107
  id: typeof c.camera_id === "string" ? c.camera_id : null,
6888
7108
  name: typeof c.name === "string" ? c.name : null
6889
7109
  })).filter((c) => c.id !== null);
@@ -7028,11 +7248,11 @@ var MediaRefListeFeld = ({ feld, wert, onChange, readOnly }) => {
7028
7248
  }
7029
7249
  const schreiben = (neu) => onChange(
7030
7250
  feld.path,
7031
- schreibListe(neu.map((e, i) => isObject9(e) ? { ...e, position: i } : e))
7251
+ schreibListe(neu.map((e, i) => isObject10(e) ? { ...e, position: i } : e))
7032
7252
  );
7033
7253
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__liste", "data-testid": `feld-${feld.path}`, children: [
7034
7254
  liste.map((eintrag, index) => {
7035
- const objekt = isObject9(eintrag) ? eintrag : {};
7255
+ const objekt = isObject10(eintrag) ? eintrag : {};
7036
7256
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__liste-zeile", children: [
7037
7257
  /* @__PURE__ */ jsx(
7038
7258
  "input",
@@ -7041,7 +7261,7 @@ var MediaRefListeFeld = ({ feld, wert, onChange, readOnly }) => {
7041
7261
  value: typeof objekt.asset_id === "string" ? objekt.asset_id : "",
7042
7262
  readOnly,
7043
7263
  placeholder: "asset_id (UUID)",
7044
- onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject9(x) ? x : {}, asset_id: e.target.value } : x))
7264
+ onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject10(x) ? x : {}, asset_id: e.target.value } : x))
7045
7265
  }
7046
7266
  ),
7047
7267
  /* @__PURE__ */ jsxs(
@@ -7050,7 +7270,7 @@ var MediaRefListeFeld = ({ feld, wert, onChange, readOnly }) => {
7050
7270
  "data-testid": `feld-${feld.path}-${index}-rolle`,
7051
7271
  value: typeof objekt.role === "string" ? objekt.role : "",
7052
7272
  disabled: readOnly,
7053
- onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject9(x) ? x : {}, role: e.target.value } : x)),
7273
+ onChange: (e) => schreiben(liste.map((x, i) => i === index ? { ...isObject10(x) ? x : {}, role: e.target.value } : x)),
7054
7274
  children: [
7055
7275
  /* @__PURE__ */ jsx("option", { value: "", children: "(Rolle w\xE4hlen)" }),
7056
7276
  rollen.map((r) => /* @__PURE__ */ jsx("option", { value: r, children: r }, r))
@@ -7093,9 +7313,10 @@ var LEERES_PROFIL = {
7093
7313
  var listeAus = (text) => text.split(",").map((t) => t.trim()).filter((t) => t.length > 0);
7094
7314
  var AusfuehrungsprofileFeld = ({ feld, wert, onChange, readOnly }) => {
7095
7315
  const gelesen = leseListe(wert);
7096
- const profile = (gelesen ?? []).filter(isObject9);
7316
+ const profile = (gelesen ?? []).filter(isObject10);
7097
7317
  const unlesbar = gelesen === null;
7098
7318
  const schreibe = (neu) => onChange(feld.path, schreibListe(neu));
7319
+ const alleBefunde = checkImageExecutionProfiles(profile);
7099
7320
  const aendere = (index, patch) => schreibe(profile.map((p, i) => i === index ? { ...p, ...patch } : p));
7100
7321
  if (unlesbar) {
7101
7322
  return /* @__PURE__ */ jsx("p", { role: "alert", "data-testid": `feld-${feld.path}-unlesbar`, children: "Der gespeicherte Wert ist keine Profilliste. Er bleibt unver\xE4ndert stehen; bitte an der Quelle korrigieren." });
@@ -7103,7 +7324,7 @@ var AusfuehrungsprofileFeld = ({ feld, wert, onChange, readOnly }) => {
7103
7324
  return /* @__PURE__ */ jsxs("div", { className: "szenen-feld__profile", "data-testid": `feld-${feld.path}`, children: [
7104
7325
  profile.length === 0 && /* @__PURE__ */ jsx("p", { "data-testid": `feld-${feld.path}-keine`, children: "Dieses Zielmodell wird f\xFCr die Prompt-Optimierung verwendet und ist derzeit nicht direkt aus der App aufrufbar." }),
7105
7326
  profile.map((profil, index) => {
7106
- const befunde = checkImageExecutionProfile(profil);
7327
+ const befunde = alleBefunde[index] ?? [];
7107
7328
  const text = (schluessel) => typeof profil[schluessel] === "string" ? profil[schluessel] : "";
7108
7329
  const liste = (schluessel) => Array.isArray(profil[schluessel]) ? profil[schluessel].join(", ") : "";
7109
7330
  return /* @__PURE__ */ jsxs("fieldset", { "data-testid": `profil-${index}`, className: "szenen-feld__profil", children: [
@@ -7854,60 +8075,72 @@ var CapabilityPanel = ({ port, elementId, setupPayload }) => {
7854
8075
  ] });
7855
8076
  };
7856
8077
 
7857
- // src/features/szenen/areas/ChainPromptAction.tsx
8078
+ // src/features/szenen/areas/PromptStartAction.tsx
7858
8079
  import { useState as useState6 } from "react";
7859
- import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
7860
- var ChainPromptAction = ({
8080
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
8081
+ var PromptStartAction = ({
7861
8082
  port,
7862
- shotElementId
8083
+ source,
8084
+ hinweise = [],
8085
+ blocker = null,
8086
+ onLauf
7863
8087
  }) => {
7864
8088
  const [lauf, setLauf] = useState6(null);
7865
8089
  const [meldung, setMeldung] = useState6(null);
7866
8090
  const [ausgang, setAusgang] = useState6(null);
7867
8091
  const [laeuft, setLaeuft] = useState6(false);
7868
8092
  const runs = port.runs;
8093
+ const ausKette = source.kind === "draft_chain";
8094
+ const id = (name) => ausKette ? `kette-${name}` : `szene-${name}`;
7869
8095
  async function erzeugen() {
7870
8096
  setLaeuft(true);
7871
8097
  setMeldung(null);
7872
8098
  setAusgang(null);
7873
8099
  try {
7874
- const ergebnis = await runs.startRunFromDraft({ shotElementId });
8100
+ const ergebnis = source.kind === "draft_chain" ? await runs.startRunFromDraft({ shotElementId: source.shotElementId }) : await runs.startRunFromScene({ sceneElementId: source.sceneElementId });
7875
8101
  if (ergebnis.kind !== "ok") {
7876
8102
  setMeldung(ergebnis.kind === "unsupported" ? `Dieser Host kann "${ergebnis.capability}" nicht.` : ergebnis.message);
7877
8103
  setAusgang(ergebnis.kind === "unsupported" ? "error" : ergebnis.kind);
7878
8104
  return;
7879
8105
  }
7880
8106
  setLauf(ergebnis.value);
8107
+ onLauf?.();
7881
8108
  } finally {
7882
8109
  setLaeuft(false);
7883
8110
  }
7884
8111
  }
7885
- return /* @__PURE__ */ jsxs5("section", { className: "szenen-kette", "data-testid": "kette-prompt-aktion", children: [
7886
- /* @__PURE__ */ jsx5("h5", { children: "Prompt aus der Draft-Kette" }),
7887
- /* @__PURE__ */ jsxs5("p", { className: "szenen-area__lead", children: [
8112
+ return /* @__PURE__ */ jsxs5("section", { className: "szenen-kette", "data-testid": id("prompt-aktion"), children: [
8113
+ /* @__PURE__ */ jsx5("h5", { children: ausKette ? "Prompt aus der Draft-Kette" : "Prompt aus dieser Szene" }),
8114
+ /* @__PURE__ */ jsx5("p", { className: "szenen-area__lead", children: ausKette ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
7888
8115
  "Dieser Shot geh\xF6rt zu einer Draft-Kette. Der Lauf friert Szene, Aufbau und Shot in dem Stand ein, den er gerade vorfindet \u2014",
7889
8116
  " ",
7890
8117
  /* @__PURE__ */ jsx5("strong", { children: "ohne" }),
7891
8118
  " dass etwas ver\xF6ffentlicht werden muss."
7892
- ] }),
8119
+ ] }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
8120
+ "Der Lauf friert diese Szene in dem Stand ein, den er gerade vorfindet. Bildaufbau, Kamera und Zielmodell sind ",
8121
+ /* @__PURE__ */ jsx5("strong", { children: "nicht n\xF6tig" }),
8122
+ " \u2014 was fehlt, wird weggelassen und am Lauf festgehalten, nicht erg\xE4nzt."
8123
+ ] }) }),
8124
+ hinweise.length > 0 && /* @__PURE__ */ jsx5("ul", { className: "szenen-detail__hint", "data-testid": id("hinweise"), role: "status", children: hinweise.map((hinweis, i) => /* @__PURE__ */ jsx5("li", { children: hinweis }, i)) }),
8125
+ blocker && /* @__PURE__ */ jsx5("p", { className: "szenen-error", role: "alert", "data-testid": id("blocker"), children: blocker }),
7893
8126
  /* @__PURE__ */ jsx5(
7894
8127
  "button",
7895
8128
  {
7896
8129
  type: "button",
7897
- disabled: laeuft,
8130
+ disabled: laeuft || blocker !== null,
7898
8131
  onClick: () => void erzeugen(),
7899
- "data-testid": "kette-prompt",
7900
- children: laeuft ? "Pr\xFCft und erzeugt \u2026" : "Draft-Kette pr\xFCfen und Prompt erzeugen (kostet einen Modellaufruf)"
8132
+ "data-testid": id("prompt"),
8133
+ children: laeuft ? "Pr\xFCft und erzeugt \u2026" : ausKette ? "Draft-Kette pr\xFCfen und Prompt erzeugen (kostet einen Modellaufruf)" : "Prompt erzeugen (kostet einen Modellaufruf)"
7901
8134
  }
7902
8135
  ),
7903
- meldung && /* @__PURE__ */ jsxs5("div", { className: "szenen-error", role: "alert", "data-testid": "kette-meldung", children: [
8136
+ meldung && /* @__PURE__ */ jsxs5("div", { className: "szenen-error", role: "alert", "data-testid": id("meldung"), children: [
7904
8137
  /* @__PURE__ */ jsx5("p", { children: meldung }),
7905
- /* @__PURE__ */ jsx5("p", { "data-testid": "kette-kein-modell", children: /* @__PURE__ */ jsx5("strong", { children: "Es wurde kein Modell gerufen." }) }),
7906
- ausgang === "conflict" && /* @__PURE__ */ jsx5("p", { "data-testid": "kette-konflikt", children: "Ein Entwurf der Kette wurde zwischenzeitlich ge\xE4ndert. Ein erneuter Versuch friert den aktuellen Stand ein." }),
7907
- ausgang === "rejected" && /* @__PURE__ */ jsx5("p", { "data-testid": "kette-mangel", children: "Die Kette selbst ist noch nicht vollst\xE4ndig. Ein erneuter Versuch \xE4ndert daran nichts \u2014 die Entw\xFCrfe m\xFCssen zuerst erg\xE4nzt werden." }),
7908
- ausgang === "error" && /* @__PURE__ */ jsx5("p", { "data-testid": "kette-technisch", children: "Das war ein technisches Problem beim Zugriff, kein Mangel der Kette. Ein erneuter Versuch ist sinnvoll." })
8138
+ /* @__PURE__ */ jsx5("p", { "data-testid": id("kein-modell"), children: /* @__PURE__ */ jsx5("strong", { children: "Es wurde kein Modell gerufen." }) }),
8139
+ ausgang === "conflict" && /* @__PURE__ */ jsx5("p", { "data-testid": id("konflikt"), children: ausKette ? "Ein Entwurf der Kette wurde zwischenzeitlich ge\xE4ndert. Ein erneuter Versuch friert den aktuellen Stand ein." : "Die Szene wurde zwischenzeitlich ge\xE4ndert. Ein erneuter Versuch friert den aktuellen Stand ein." }),
8140
+ ausgang === "rejected" && /* @__PURE__ */ jsx5("p", { "data-testid": id("mangel"), children: ausKette ? "Die Kette selbst ist noch nicht vollst\xE4ndig. Ein erneuter Versuch \xE4ndert daran nichts \u2014 die Entw\xFCrfe m\xFCssen zuerst erg\xE4nzt werden." : "Aus diesem Stand l\xE4sst sich kein Auftrag herstellen. Ein erneuter Versuch \xE4ndert daran nichts \u2014 die Szene muss zuerst Inhalt bekommen." }),
8141
+ ausgang === "error" && /* @__PURE__ */ jsx5("p", { "data-testid": id("technisch"), children: "Das war ein technisches Problem beim Zugriff, kein fachlicher Mangel. Ein erneuter Versuch ist sinnvoll." })
7909
8142
  ] }),
7910
- lauf && /* @__PURE__ */ jsxs5("div", { className: "szenen-run", "data-testid": "kette-lauf", children: [
8143
+ lauf && /* @__PURE__ */ jsxs5("div", { className: "szenen-run", "data-testid": id("lauf"), children: [
7911
8144
  /* @__PURE__ */ jsxs5("h5", { children: [
7912
8145
  "Prompt-Lauf ",
7913
8146
  lauf.status === "succeeded" ? "gelungen" : "gescheitert"
@@ -7919,7 +8152,7 @@ var ChainPromptAction = ({
7919
8152
  /* @__PURE__ */ jsx5("code", { children: lauf.model_id }),
7920
8153
  "."
7921
8154
  ] }),
7922
- lauf.status === "succeeded" && lauf.output && /* @__PURE__ */ jsx5("pre", { className: "szenen-proposal__payload", "data-testid": "kette-prompt-text", children: lauf.output.positive }),
8155
+ lauf.status === "succeeded" && lauf.output && /* @__PURE__ */ jsx5("pre", { className: "szenen-proposal__payload", "data-testid": id("prompt-text"), children: lauf.output.positive }),
7923
8156
  lauf.status === "failed" && /* @__PURE__ */ jsxs5("p", { className: "szenen-error", children: [
7924
8157
  lauf.failure?.class,
7925
8158
  " \u2014 ",
@@ -8051,7 +8284,7 @@ import { useState as useState8 } from "react";
8051
8284
 
8052
8285
  // src/features/szenen/areas/RunImagesPanel.tsx
8053
8286
  import { useState as useState7 } from "react";
8054
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
8287
+ import { Fragment as Fragment3, jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
8055
8288
  var AUFTRAG_TEXT = {
8056
8289
  // „gestartet/unterbrochen" in einem: Aus dem Log allein ist beides nicht
8057
8290
  // unterscheidbar, und genau das ist beabsichtigt — es gibt keinen
@@ -8089,12 +8322,27 @@ var RunImagesPanel = ({ port, lauf }) => {
8089
8322
  "Lauf ",
8090
8323
  /* @__PURE__ */ jsx7("code", { "data-testid": `eingang-lauf-${lauf.run_id}`, children: lauf.run_id })
8091
8324
  ] }),
8092
- quelle.kind === "published" ? /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8325
+ quelle.kind === "published" && /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8093
8326
  "ver\xF6ffentlichte Shot-Version ",
8094
8327
  /* @__PURE__ */ jsx7("code", { children: quelle.shot_version_id })
8095
- ] }) : /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8328
+ ] }),
8329
+ quelle.kind === "draft_chain" && /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8096
8330
  "Draft-Kette ",
8097
8331
  /* @__PURE__ */ jsx7("code", { children: quelle.chain_id })
8332
+ ] }),
8333
+ quelle.kind === "scene_direct" && /* @__PURE__ */ jsxs7("span", { "data-testid": `eingang-herkunft-${lauf.run_id}`, children: [
8334
+ "Szene ",
8335
+ /* @__PURE__ */ jsx7("code", { children: quelle.scene.element_id }),
8336
+ quelle.scene.draft_id ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
8337
+ " \xB7 Entwurf ",
8338
+ /* @__PURE__ */ jsx7("code", { children: quelle.scene.draft_id }),
8339
+ " (Revision ",
8340
+ quelle.scene.revision,
8341
+ ")"
8342
+ ] }) : /* @__PURE__ */ jsxs7(Fragment3, { children: [
8343
+ " \xB7 Version ",
8344
+ /* @__PURE__ */ jsx7("code", { children: quelle.scene.version_id })
8345
+ ] })
8098
8346
  ] })
8099
8347
  ] }),
8100
8348
  quelle.kind === "draft_chain" && quelle.derivation_run_id ? /* @__PURE__ */ jsx7(
@@ -8319,7 +8567,7 @@ var ErzeugenAktion = ({ port, lauf, wahl, wahlFehler, onFertig }) => {
8319
8567
  return (
8320
8568
  // Kein Fehler und kein Grund, den Lauf zu sperren: Der externe
8321
8569
  // Importweg bleibt daneben stehen (D-104.5).
8322
- /* @__PURE__ */ jsxs7(Fragment2, { children: [
8570
+ /* @__PURE__ */ jsxs7(Fragment3, { children: [
8323
8571
  /* @__PURE__ */ jsxs7("p", { "data-testid": `erzeugen-unsupported-modell-${lauf.run_id}`, children: [
8324
8572
  "Hier kann derzeit kein Bild erzeugt werden:",
8325
8573
  " ",
@@ -8377,7 +8625,7 @@ var ErzeugenAktion = ({ port, lauf, wahl, wahlFehler, onFertig }) => {
8377
8625
  return /* @__PURE__ */ jsxs7("div", { className: "szenen-bilder__aktion", "data-testid": `erzeugen-${lauf.run_id}`, children: [
8378
8626
  /* @__PURE__ */ jsx7("h5", { children: "Bilder aus diesem Prompt erzeugen" }),
8379
8627
  /* @__PURE__ */ jsx7(ProfilBefunde, { wahl, runId: lauf.run_id }),
8380
- /* @__PURE__ */ jsx7("p", { "data-testid": `erzeugen-zielmodell-${lauf.run_id}`, children: wahl.prompt_target_model_key ? /* @__PURE__ */ jsxs7(Fragment2, { children: [
8628
+ /* @__PURE__ */ jsx7("p", { "data-testid": `erzeugen-zielmodell-${lauf.run_id}`, children: wahl.prompt_target_model_key ? /* @__PURE__ */ jsxs7(Fragment3, { children: [
8381
8629
  "Prompt optimiert f\xFCr ",
8382
8630
  /* @__PURE__ */ jsx7("code", { children: wahl.prompt_target_model_key })
8383
8631
  ] }) : "Dieser Lauf tr\xE4gt keine Optimierungsabsicht (kein target_model)." }),
@@ -8561,7 +8809,7 @@ var ZuordnenAktion = ({ port, lauf, onFertig }) => {
8561
8809
  }
8562
8810
  )
8563
8811
  ] }),
8564
- dateien.length > 0 && /* @__PURE__ */ jsxs7(Fragment2, { children: [
8812
+ dateien.length > 0 && /* @__PURE__ */ jsxs7(Fragment3, { children: [
8565
8813
  /* @__PURE__ */ jsxs7("label", { children: [
8566
8814
  "Modell (f\xFCr alle Bilder, leer = unbekannt)",
8567
8815
  /* @__PURE__ */ jsx7(
@@ -8660,9 +8908,13 @@ var RunsPanel = ({ port, source, contextId }) => {
8660
8908
  const [notiz, setNotiz] = useState8(null);
8661
8909
  const [nachladen, setNachladen] = useState8(0);
8662
8910
  const faehig = capabilitiesOf(port);
8663
- const quellSchluessel = source.kind === "published" ? source.shotVersionId : source.chainId;
8911
+ const quellSchluessel = source.kind === "published" ? source.shotVersionId : source.kind === "draft_chain" ? source.chainId : source.sceneElementId;
8664
8912
  const [phase, neuLaden] = usePortQuery(
8665
- () => source.kind === "published" ? port.runs.listRunsForShot(source.shotVersionId) : port.runs.listRunsForChain(source.chainId),
8913
+ () => {
8914
+ if (source.kind === "published") return port.runs.listRunsForShot(source.shotVersionId);
8915
+ if (source.kind === "draft_chain") return port.runs.listRunsForChain(source.chainId);
8916
+ return port.runs.listRunsForScene(source.sceneElementId);
8917
+ },
8666
8918
  [port, source.kind, quellSchluessel, nachladen]
8667
8919
  );
8668
8920
  const starten = async () => {
@@ -8701,7 +8953,7 @@ var RunsPanel = ({ port, source, contextId }) => {
8701
8953
  "L\xE4ufe konnten nicht geladen werden: ",
8702
8954
  phase.message
8703
8955
  ] }),
8704
- phase.status === "ready" && laeufe.length === 0 && /* @__PURE__ */ jsx8("p", { "data-testid": "keine-laeufe", children: source.kind === "published" ? "F\xFCr diese Shot-Version gibt es noch keinen Lauf." : "F\xFCr diese Draft-Kette gibt es noch keinen Lauf." }),
8956
+ phase.status === "ready" && laeufe.length === 0 && /* @__PURE__ */ jsx8("p", { "data-testid": "keine-laeufe", children: source.kind === "published" ? "F\xFCr diese Shot-Version gibt es noch keinen Lauf." : source.kind === "draft_chain" ? "F\xFCr diese Draft-Kette gibt es noch keinen Lauf." : "F\xFCr diese Szene gibt es noch keinen direkten Lauf." }),
8705
8957
  /* @__PURE__ */ jsx8("ol", { "data-testid": "runden-liste", children: laeufe.map((lauf) => /* @__PURE__ */ jsx8(
8706
8958
  RundenEintrag,
8707
8959
  {
@@ -8794,7 +9046,7 @@ var RundenEintrag = ({ port, lauf, runde, itemMoeglich, onItemGespeichert }) =>
8794
9046
  };
8795
9047
 
8796
9048
  // src/features/szenen/areas/ElementDetail.tsx
8797
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
9049
+ import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs9 } from "react/jsx-runtime";
8798
9050
  var STRUKTURELL_BEDIENT = {
8799
9051
  scene: ["nodes", "relations"]
8800
9052
  };
@@ -8906,6 +9158,23 @@ var ElementDetail = ({
8906
9158
  if (!kette2) return null;
8907
9159
  return kette2.links[0]?.field ?? null;
8908
9160
  }, [schnappschuss?.draft?.chain]);
9161
+ const laufStand = useMemo2(() => {
9162
+ if (!schnappschuss || schnappschuss.element.type !== "scene") return null;
9163
+ if (schnappschuss.draft) return schnappschuss.draft.payload;
9164
+ const kopf = usableHeadVersionId(kopfAufloesung);
9165
+ if (!kopf) return null;
9166
+ return schnappschuss.versions.find((v) => v.version_id === kopf)?.payload ?? null;
9167
+ }, [schnappschuss, kopfAufloesung]);
9168
+ const szenenBlocker = useMemo2(() => {
9169
+ if (!schnappschuss || schnappschuss.element.type !== "scene") return null;
9170
+ if (laufStand === null) {
9171
+ return schnappschuss.versions.length > 0 ? "Diese Szene hat keinen Entwurf und in diesem Kontext keinen bevorzugten Kopf. Welcher Stand gilt, entscheidet keine Reihenfolge (D-36) \u2014 bitte oben eine Version als bevorzugt setzen." : "Diese Szene hat noch keinen gespeicherten Stand. Ein Lauf friert ein, was gespeichert ist \u2014 bitte zuerst den Entwurf speichern.";
9172
+ }
9173
+ const flag = sceneOnlyCapabilities(laufStand).can_render_prompt;
9174
+ if (flag.state === "yes") return null;
9175
+ const grund = flag.reasons[0];
9176
+ return grund && "message" in grund ? grund.message : "Kein Lauf moeglich.";
9177
+ }, [schnappschuss, laufStand]);
8909
9178
  const vorschau = useMemo2(() => {
8910
9179
  if (!schnappschuss) return null;
8911
9180
  try {
@@ -9039,8 +9308,7 @@ var ElementDetail = ({
9039
9308
  /* @__PURE__ */ jsxs9("header", { children: [
9040
9309
  /* @__PURE__ */ jsx9("h3", { children: schnappschuss.metadata?.title ?? "(ohne Titel)" }),
9041
9310
  /* @__PURE__ */ jsxs9("p", { className: "szenen-detail__ids", children: [
9042
- /* @__PURE__ */ jsx9("span", { children: typ }),
9043
- /* @__PURE__ */ jsx9("code", { children: schnappschuss.element.element_id }),
9311
+ /* @__PURE__ */ jsx9("span", { "data-testid": "element-typ", children: elementTypLabel(typ) }),
9044
9312
  schnappschuss.element.retired && /* @__PURE__ */ jsx9("span", { "data-testid": "ist-stillgelegt", children: "stillgelegt" })
9045
9313
  ] })
9046
9314
  ] }),
@@ -9084,10 +9352,10 @@ var ElementDetail = ({
9084
9352
  /* @__PURE__ */ jsxs9("p", { children: [
9085
9353
  "Es gibt bereits einen Entwurf (Revision ",
9086
9354
  draft.revision,
9087
- draft.base_version_id ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
9355
+ draft.base_version_id ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
9088
9356
  " auf Basis ",
9089
9357
  /* @__PURE__ */ jsx9("code", { children: draft.base_version_id })
9090
- ] }) : /* @__PURE__ */ jsx9(Fragment3, { children: " ohne Basis" }),
9358
+ ] }) : /* @__PURE__ */ jsx9(Fragment4, { children: " ohne Basis" }),
9091
9359
  "). Ihn auf Version ",
9092
9360
  /* @__PURE__ */ jsx9("code", { children: basiswechsel }),
9093
9361
  " neu aufzusetzen",
@@ -9119,13 +9387,13 @@ var ElementDetail = ({
9119
9387
  )
9120
9388
  ] }),
9121
9389
  /* @__PURE__ */ jsxs9("section", { className: "szenen-detail__draft", "data-testid": "draft-bereich", children: [
9122
- /* @__PURE__ */ jsx9("h4", { children: bearbeitbar ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
9390
+ /* @__PURE__ */ jsx9("h4", { children: bearbeitbar ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
9123
9391
  "Entwurf",
9124
9392
  draft && /* @__PURE__ */ jsxs9("span", { children: [
9125
9393
  " \xB7 Revision ",
9126
9394
  draft.revision
9127
9395
  ] })
9128
- ] }) : /* @__PURE__ */ jsx9(Fragment3, { children: "Ver\xF6ffentlichte Version \u2014 nur Ansicht" }) }),
9396
+ ] }) : /* @__PURE__ */ jsx9(Fragment4, { children: "Ver\xF6ffentlichte Version \u2014 nur Ansicht" }) }),
9129
9397
  angezeigt.kind === "keiner" && /* @__PURE__ */ jsxs9("p", { "data-testid": "nichts-angezeigt", children: [
9130
9398
  "Es ist kein Stand ausgew\xE4hlt. Oben eine Version anzeigen oder \xFCber ",
9131
9399
  /* @__PURE__ */ jsx9("strong", { children: "als Grundlage bearbeiten" }),
@@ -9136,7 +9404,7 @@ var ElementDetail = ({
9136
9404
  /* @__PURE__ */ jsx9("strong", { children: "als Grundlage bearbeiten" }),
9137
9405
  " w\xE4hlen \u2014 das erzeugt einen Entwurf mit genau dieser Version als Basis."
9138
9406
  ] }),
9139
- angezeigt.kind !== "keiner" && /* @__PURE__ */ jsxs9(Fragment3, { children: [
9407
+ angezeigt.kind !== "keiner" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
9140
9408
  typ === "scene" && /* @__PURE__ */ jsx9(
9141
9409
  SceneEditor,
9142
9410
  {
@@ -9216,12 +9484,15 @@ var ElementDetail = ({
9216
9484
  // einer Draft-Kette, fuehrt der Weg ueber das Einfrieren —
9217
9485
  // der alte Satz „setzen eine veroeffentlichte Version
9218
9486
  // voraus" gilt nur noch fuer den Einzel-Shot.
9219
- draft?.chain ? /* @__PURE__ */ jsxs9(Fragment3, { children: [
9487
+ draft?.chain ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
9220
9488
  /* @__PURE__ */ jsx9(
9221
- ChainPromptAction,
9489
+ PromptStartAction,
9222
9490
  {
9223
9491
  port,
9224
- shotElementId: schnappschuss.element.element_id
9492
+ source: {
9493
+ kind: "draft_chain",
9494
+ shotElementId: schnappschuss.element.element_id
9495
+ }
9225
9496
  }
9226
9497
  ),
9227
9498
  /* @__PURE__ */ jsx9(
@@ -9241,12 +9512,36 @@ var ElementDetail = ({
9241
9512
  source: { kind: "published", shotVersionId: laufVersionId }
9242
9513
  }
9243
9514
  ) : /* @__PURE__ */ jsx9("p", { "data-testid": "laufquelle-unklar", children: "Dieser Shot hat mehrere ver\xF6ffentlichte Versionen und keinen bevorzugten Kopf in diesem Kontext. Welche davon einen Lauf tr\xE4gt, entscheidet keine Reihenfolge \u2014 bitte oben eine Version anzeigen oder als bevorzugt setzen." })),
9244
- typ === "scene_setup" && /* @__PURE__ */ jsx9(
9245
- CapabilityPanel,
9246
- {
9247
- port,
9248
- elementId,
9249
- setupPayload: payloadAusFormular()
9515
+ typ === "scene" && /* @__PURE__ */ jsxs9(Fragment4, { children: [
9516
+ /* @__PURE__ */ jsx9(
9517
+ PromptStartAction,
9518
+ {
9519
+ port,
9520
+ source: { kind: "scene", sceneElementId: schnappschuss.element.element_id },
9521
+ hinweise: [
9522
+ "Kein Bildaufbau und keine Kamera \u2014 der Prompt wird ohne Kameravorgabe erzeugt.",
9523
+ "Kein Zielmodell \u2014 generische Promptableitung ohne Modelloptimierung.",
9524
+ schnappschuss.draft ? "Eingefroren wird der gespeicherte Entwurf. Nicht gespeicherte Aenderungen im Formular gehen nicht mit." : "Eingefroren wird die wirksame veroeffentlichte Version."
9525
+ ],
9526
+ blocker: szenenBlocker,
9527
+ onLauf: () => setNachladen((n) => n + 1)
9528
+ }
9529
+ ),
9530
+ /* @__PURE__ */ jsx9(
9531
+ RunsPanel,
9532
+ {
9533
+ port,
9534
+ contextId,
9535
+ source: { kind: "scene", sceneElementId: schnappschuss.element.element_id }
9536
+ }
9537
+ )
9538
+ ] }),
9539
+ typ === "scene_setup" && /* @__PURE__ */ jsx9(
9540
+ CapabilityPanel,
9541
+ {
9542
+ port,
9543
+ elementId,
9544
+ setupPayload: payloadAusFormular()
9250
9545
  }
9251
9546
  ),
9252
9547
  notiz && /* @__PURE__ */ jsxs9(
@@ -9265,6 +9560,26 @@ var ElementDetail = ({
9265
9560
  ] });
9266
9561
  };
9267
9562
 
9563
+ // src/features/szenen/areas/useSchmalesDisplay.ts
9564
+ import { useEffect as useEffect4, useState as useState10 } from "react";
9565
+ var SCHMALE_ANSICHT = "(max-width: 760px)";
9566
+ function messen(abfrage) {
9567
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
9568
+ return window.matchMedia(abfrage).matches;
9569
+ }
9570
+ function useSchmalesDisplay(abfrage = SCHMALE_ANSICHT) {
9571
+ const [schmal, setSchmal] = useState10(() => messen(abfrage));
9572
+ useEffect4(() => {
9573
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
9574
+ const liste = window.matchMedia(abfrage);
9575
+ const aktualisieren = () => setSchmal(liste.matches);
9576
+ aktualisieren();
9577
+ liste.addEventListener?.("change", aktualisieren);
9578
+ return () => liste.removeEventListener?.("change", aktualisieren);
9579
+ }, [abfrage]);
9580
+ return schmal;
9581
+ }
9582
+
9268
9583
  // src/features/szenen/areas/ElementsArea.tsx
9269
9584
  import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
9270
9585
  var ElementsArea = ({
@@ -9273,18 +9588,31 @@ var ElementsArea = ({
9273
9588
  author = "szenen-view",
9274
9589
  restrictToTypes,
9275
9590
  allTypesLabel,
9591
+ listTitle,
9276
9592
  onSelect
9277
9593
  }) => {
9278
9594
  const auswahlTypen = restrictToTypes ?? SZENEN_ELEMENT_TYPES;
9279
- const [typ, setTyp] = useState10(
9280
- restrictToTypes && restrictToTypes.length === 1 ? restrictToTypes[0] : ""
9281
- );
9282
- const [zeigeStillgelegte, setZeigeStillgelegte] = useState10(false);
9283
- const [gewaehlt, setGewaehlt] = useState10(null);
9284
- const [neuerTitel, setNeuerTitel] = useState10("");
9285
- const [neuerTyp, setNeuerTyp] = useState10(auswahlTypen[0]);
9286
- const [notiz, setNotiz] = useState10(null);
9287
- const [anlegend, setAnlegend] = useState10(false);
9595
+ const einzelTyp = auswahlTypen.length === 1 ? auswahlTypen[0] : null;
9596
+ const gemischt = auswahlTypen.length > 1;
9597
+ const ueberschrift = listTitle ?? (einzelTyp ? elementTypPlural(einzelTyp) : "Bausteine");
9598
+ const einzahl = einzelTyp ? elementTypLabel(einzelTyp) : "Objekt";
9599
+ const [typ, setTyp] = useState11(einzelTyp ?? "");
9600
+ const [zeigeStillgelegte, setZeigeStillgelegte] = useState11(false);
9601
+ const [gewaehlt, setGewaehlt] = useState11(null);
9602
+ const [neuerTitel, setNeuerTitel] = useState11("");
9603
+ const [neuerTyp, setNeuerTyp] = useState11(auswahlTypen[0]);
9604
+ const [notiz, setNotiz] = useState11(null);
9605
+ const [anlegend, setAnlegend] = useState11(false);
9606
+ const [anlageOffen, setAnlageOffen] = useState11(false);
9607
+ const schmal = useSchmalesDisplay();
9608
+ const [ansicht, setAnsicht] = useState11("liste");
9609
+ const zeigeListe = !schmal || ansicht === "liste";
9610
+ const zeigeDetail = !schmal || ansicht === "detail";
9611
+ const waehle = (elementId) => {
9612
+ setGewaehlt(elementId);
9613
+ setAnsicht("detail");
9614
+ onSelect?.(elementId);
9615
+ };
9288
9616
  const [phase, neuLaden] = usePortQuery(
9289
9617
  () => port.elements.listElements({
9290
9618
  contextId,
@@ -9293,128 +9621,199 @@ var ElementsArea = ({
9293
9621
  }),
9294
9622
  [port, contextId, typ, zeigeStillgelegte]
9295
9623
  );
9296
- return /* @__PURE__ */ jsxs10("div", { className: "szenen-elements", "data-testid": "bereich-elemente", children: [
9297
- /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__filter", children: [
9298
- /* @__PURE__ */ jsxs10("label", { children: [
9299
- "Typ",
9300
- /* @__PURE__ */ jsxs10(
9301
- "select",
9302
- {
9303
- "data-testid": "filter-typ",
9304
- value: typ,
9305
- onChange: (e) => setTyp(e.target.value),
9306
- children: [
9307
- (!restrictToTypes || restrictToTypes.length > 1) && /* @__PURE__ */ jsx10("option", { value: "", children: allTypesLabel ?? "alle Typen" }),
9308
- auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: t }, t))
9309
- ]
9310
- }
9311
- )
9312
- ] }),
9313
- /* @__PURE__ */ jsxs10("label", { children: [
9314
- /* @__PURE__ */ jsx10(
9315
- "input",
9316
- {
9317
- type: "checkbox",
9318
- "data-testid": "filter-stillgelegt",
9319
- checked: zeigeStillgelegte,
9320
- onChange: (e) => setZeigeStillgelegte(e.target.checked)
9321
- }
9322
- ),
9323
- "stillgelegte Elemente einblenden"
9324
- ] }),
9325
- /* @__PURE__ */ jsx10("button", { type: "button", "data-testid": "neu-laden", onClick: neuLaden, children: "neu laden" })
9326
- ] }),
9327
- /* @__PURE__ */ jsxs10(
9328
- "form",
9329
- {
9330
- className: "szenen-elements__create",
9331
- "data-testid": "element-anlegen",
9332
- onSubmit: async (e) => {
9333
- e.preventDefault();
9334
- if (!neuerTitel.trim()) return;
9335
- setAnlegend(true);
9336
- const ergebnis = await port.elements.createElement({
9337
- type: neuerTyp,
9338
- title: neuerTitel.trim(),
9339
- contextId
9340
- });
9341
- setNotiz(noticeFor(ergebnis, `Element \u201E${neuerTitel.trim()}" anlegen`));
9342
- setAnlegend(false);
9343
- if (ergebnis.kind === "ok") {
9344
- setNeuerTitel("");
9345
- setGewaehlt(ergebnis.value.element_id);
9346
- onSelect?.(ergebnis.value.element_id);
9347
- neuLaden();
9348
- }
9349
- },
9350
- children: [
9351
- /* @__PURE__ */ jsx10(
9352
- "input",
9624
+ const anlageSchliessen = () => {
9625
+ setAnlageOffen(false);
9626
+ setNeuerTitel("");
9627
+ };
9628
+ return /* @__PURE__ */ jsxs10(
9629
+ "div",
9630
+ {
9631
+ className: "szenen-elements",
9632
+ "data-testid": "bereich-elemente",
9633
+ "data-ansicht": schmal ? ansicht : "beide",
9634
+ children: [
9635
+ zeigeListe && /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__master", "data-testid": "elemente-master", children: [
9636
+ /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__toolbar", children: [
9637
+ /* @__PURE__ */ jsx10("h3", { className: "szenen-elements__heading", children: ueberschrift }),
9638
+ /* @__PURE__ */ jsx10(
9639
+ "button",
9640
+ {
9641
+ type: "button",
9642
+ className: "szenen-elements__new",
9643
+ "data-testid": "neu-oeffnen",
9644
+ "aria-expanded": anlageOffen,
9645
+ onClick: () => {
9646
+ setNotiz(null);
9647
+ if (anlageOffen) anlageSchliessen();
9648
+ else setAnlageOffen(true);
9649
+ },
9650
+ children: "+ Neu"
9651
+ }
9652
+ )
9653
+ ] }),
9654
+ gemischt && /* @__PURE__ */ jsxs10("label", { className: "szenen-elements__scope", children: [
9655
+ "Art",
9656
+ /* @__PURE__ */ jsxs10(
9657
+ "select",
9658
+ {
9659
+ "data-testid": "filter-typ",
9660
+ value: typ,
9661
+ onChange: (e) => setTyp(e.target.value),
9662
+ children: [
9663
+ /* @__PURE__ */ jsx10("option", { value: "", children: allTypesLabel ?? "alle Typen" }),
9664
+ auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: elementTypPlural(t) }, t))
9665
+ ]
9666
+ }
9667
+ )
9668
+ ] }),
9669
+ anlageOffen && /* @__PURE__ */ jsxs10(
9670
+ "form",
9353
9671
  {
9354
- "data-testid": "neuer-titel",
9355
- value: neuerTitel,
9356
- placeholder: "Titel des neuen Elements",
9357
- onChange: (e) => setNeuerTitel(e.target.value)
9672
+ className: "szenen-elements__create",
9673
+ "data-testid": "element-anlegen",
9674
+ onSubmit: async (e) => {
9675
+ e.preventDefault();
9676
+ if (!neuerTitel.trim()) return;
9677
+ setAnlegend(true);
9678
+ const gewuenschterTyp = einzelTyp ?? neuerTyp;
9679
+ const titel = neuerTitel.trim();
9680
+ const ergebnis = await port.elements.createElement({
9681
+ type: gewuenschterTyp,
9682
+ title: titel,
9683
+ contextId
9684
+ });
9685
+ setNotiz(noticeFor(
9686
+ ergebnis,
9687
+ `${elementTypLabel(gewuenschterTyp)} \u201E${titel}" anlegen`
9688
+ ));
9689
+ setAnlegend(false);
9690
+ if (ergebnis.kind === "ok") {
9691
+ anlageSchliessen();
9692
+ waehle(ergebnis.value.element_id);
9693
+ neuLaden();
9694
+ }
9695
+ },
9696
+ children: [
9697
+ /* @__PURE__ */ jsxs10("label", { className: "szenen-elements__create-title", children: [
9698
+ einzelTyp ? `Neue ${einzahl}` : "Titel",
9699
+ /* @__PURE__ */ jsx10(
9700
+ "input",
9701
+ {
9702
+ "data-testid": "neuer-titel",
9703
+ value: neuerTitel,
9704
+ autoFocus: true,
9705
+ placeholder: einzelTyp ? `Titel der neuen ${einzahl}` : "Titel",
9706
+ onChange: (e) => setNeuerTitel(e.target.value)
9707
+ }
9708
+ )
9709
+ ] }),
9710
+ gemischt && /* @__PURE__ */ jsxs10("label", { className: "szenen-elements__create-type", children: [
9711
+ "Art",
9712
+ /* @__PURE__ */ jsx10(
9713
+ "select",
9714
+ {
9715
+ "data-testid": "neuer-typ",
9716
+ value: neuerTyp,
9717
+ onChange: (e) => setNeuerTyp(e.target.value),
9718
+ children: auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: elementTypLabel(t) }, t))
9719
+ }
9720
+ )
9721
+ ] }),
9722
+ /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__create-actions", children: [
9723
+ /* @__PURE__ */ jsx10(
9724
+ "button",
9725
+ {
9726
+ type: "submit",
9727
+ "data-testid": "anlegen",
9728
+ disabled: anlegend || !neuerTitel.trim(),
9729
+ children: "anlegen"
9730
+ }
9731
+ ),
9732
+ /* @__PURE__ */ jsx10(
9733
+ "button",
9734
+ {
9735
+ type: "button",
9736
+ "data-testid": "anlegen-abbrechen",
9737
+ onClick: anlageSchliessen,
9738
+ children: "abbrechen"
9739
+ }
9740
+ )
9741
+ ] })
9742
+ ]
9358
9743
  }
9359
9744
  ),
9360
- /* @__PURE__ */ jsx10(
9361
- "select",
9745
+ notiz && /* @__PURE__ */ jsx10("p", { "data-testid": "anlegen-notiz", "data-tone": notiz.tone, children: notiz.text }),
9746
+ phase.status === "loading" && /* @__PURE__ */ jsx10("p", { "data-testid": "elemente-laden", children: "Elemente werden geladen \u2026" }),
9747
+ phase.status === "error" && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-fehler", role: "alert", children: [
9748
+ "Elemente konnten nicht geladen werden: ",
9749
+ phase.message,
9750
+ phase.retryable && " \u2014 ein erneuter Versuch kann helfen."
9751
+ ] }),
9752
+ phase.status === "ready" && phase.value.length === 0 && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-leer", children: [
9753
+ typ ? `Keine ${elementTypPlural(typ)} in diesem Kontext.` : "Nichts in diesem Kontext.",
9754
+ " ",
9755
+ 'Mit \u201E+ Neu" anlegen.'
9756
+ ] }),
9757
+ phase.status === "ready" && phase.value.length > 0 && /* @__PURE__ */ jsx10("ul", { className: "szenen-elements__list", "data-testid": "elemente-liste", children: phase.value.map((element) => /* @__PURE__ */ jsx10("li", { "data-element-id": element.element_id, children: /* @__PURE__ */ jsxs10(
9758
+ "button",
9759
+ {
9760
+ type: "button",
9761
+ "data-testid": `element-waehlen-${element.element_id}`,
9762
+ "aria-current": element.element_id === gewaehlt,
9763
+ className: element.element_id === gewaehlt ? "is-selected" : void 0,
9764
+ onClick: () => waehle(element.element_id),
9765
+ children: [
9766
+ /* @__PURE__ */ jsx10("strong", { className: "szenen-elements__title", children: element.title || "Unbenanntes Element" }),
9767
+ gemischt && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__type", children: elementTypLabel(element.type) }),
9768
+ element.subtype && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__subtype", children: element.subtype }),
9769
+ element.retired && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__retired", children: "stillgelegt" })
9770
+ ]
9771
+ }
9772
+ ) }, element.element_id)) }),
9773
+ /* @__PURE__ */ jsxs10("details", { className: "szenen-elements__options", "data-testid": "listen-optionen", children: [
9774
+ /* @__PURE__ */ jsx10("summary", { children: "Listenoptionen" }),
9775
+ /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__filter", children: [
9776
+ /* @__PURE__ */ jsxs10("label", { children: [
9777
+ /* @__PURE__ */ jsx10(
9778
+ "input",
9779
+ {
9780
+ type: "checkbox",
9781
+ "data-testid": "filter-stillgelegt",
9782
+ checked: zeigeStillgelegte,
9783
+ onChange: (e) => setZeigeStillgelegte(e.target.checked)
9784
+ }
9785
+ ),
9786
+ "stillgelegte Elemente einblenden"
9787
+ ] }),
9788
+ /* @__PURE__ */ jsx10("button", { type: "button", "data-testid": "neu-laden", onClick: neuLaden, children: "neu laden" })
9789
+ ] })
9790
+ ] })
9791
+ ] }),
9792
+ zeigeDetail && /* @__PURE__ */ jsxs10("div", { className: "szenen-elements__detail", "data-testid": "elemente-detail-spalte", children: [
9793
+ schmal && /* @__PURE__ */ jsx10(
9794
+ "button",
9362
9795
  {
9363
- "data-testid": "neuer-typ",
9364
- value: neuerTyp,
9365
- onChange: (e) => setNeuerTyp(e.target.value),
9366
- children: auswahlTypen.map((t) => /* @__PURE__ */ jsx10("option", { value: t, children: t }, t))
9796
+ type: "button",
9797
+ className: "szenen-elements__back",
9798
+ "data-testid": "zurueck-zur-liste",
9799
+ onClick: () => setAnsicht("liste"),
9800
+ children: "\u2190 Zur\xFCck zur Liste"
9367
9801
  }
9368
9802
  ),
9369
- /* @__PURE__ */ jsx10("button", { type: "submit", "data-testid": "anlegen", disabled: anlegend || !neuerTitel.trim(), children: "anlegen" })
9370
- ]
9371
- }
9372
- ),
9373
- notiz && /* @__PURE__ */ jsx10("p", { "data-testid": "anlegen-notiz", "data-tone": notiz.tone, children: notiz.text }),
9374
- phase.status === "loading" && /* @__PURE__ */ jsx10("p", { "data-testid": "elemente-laden", children: "Elemente werden geladen \u2026" }),
9375
- phase.status === "error" && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-fehler", role: "alert", children: [
9376
- "Elemente konnten nicht geladen werden: ",
9377
- phase.message,
9378
- phase.retryable && " \u2014 ein erneuter Versuch kann helfen."
9379
- ] }),
9380
- phase.status === "ready" && phase.value.length === 0 && /* @__PURE__ */ jsxs10("p", { "data-testid": "elemente-leer", children: [
9381
- "Keine Elemente in diesem Kontext",
9382
- typ ? ` mit Typ \u201E${typ}"` : "",
9383
- "."
9384
- ] }),
9385
- phase.status === "ready" && phase.value.length > 0 && /* @__PURE__ */ jsx10("ul", { className: "szenen-elements__list", "data-testid": "elemente-liste", children: phase.value.map((element) => /* @__PURE__ */ jsx10("li", { "data-element-id": element.element_id, children: /* @__PURE__ */ jsxs10(
9386
- "button",
9387
- {
9388
- type: "button",
9389
- "aria-current": element.element_id === gewaehlt,
9390
- className: element.element_id === gewaehlt ? "is-selected" : void 0,
9391
- onClick: () => {
9392
- setGewaehlt(element.element_id);
9393
- onSelect?.(element.element_id);
9394
- },
9395
- children: [
9396
- /* @__PURE__ */ jsx10("strong", { className: "szenen-elements__title", children: element.title || "Unbenanntes Element" }),
9397
- /* @__PURE__ */ jsx10("span", { className: "szenen-elements__type", children: element.type }),
9398
- element.subtype && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__subtype", children: element.subtype }),
9399
- /* @__PURE__ */ jsxs10("span", { className: "szenen-elements__technical", children: [
9400
- "ID ",
9401
- /* @__PURE__ */ jsx10("code", { className: "szenen-elements__id", children: element.element_id })
9402
- ] }),
9403
- element.retired && /* @__PURE__ */ jsx10("span", { className: "szenen-elements__retired", children: "stillgelegt" })
9404
- ]
9405
- }
9406
- ) }, element.element_id)) }),
9407
- gewaehlt && /* @__PURE__ */ jsx10(
9408
- ElementDetail,
9409
- {
9410
- port,
9411
- elementId: gewaehlt,
9412
- contextId,
9413
- author,
9414
- onChanged: neuLaden
9415
- }
9416
- )
9417
- ] });
9803
+ gewaehlt ? /* @__PURE__ */ jsx10(
9804
+ ElementDetail,
9805
+ {
9806
+ port,
9807
+ elementId: gewaehlt,
9808
+ contextId,
9809
+ author,
9810
+ onChanged: neuLaden
9811
+ }
9812
+ ) : /* @__PURE__ */ jsx10("p", { className: "szenen-elements__empty-detail", "data-testid": "keine-auswahl", children: "Nichts ausgew\xE4hlt. Ein Eintrag aus der Liste \xF6ffnet die Bearbeitung." })
9813
+ ] })
9814
+ ]
9815
+ }
9816
+ );
9418
9817
  };
9419
9818
 
9420
9819
  // src/features/szenen/areas/SceneArea.tsx
@@ -9427,14 +9826,15 @@ var SceneArea = ({ port, contextId }) => /* @__PURE__ */ jsxs11("div", { classNa
9427
9826
  // src/features/szenen/areas/SetupArea.tsx
9428
9827
  import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
9429
9828
  var SetupArea = ({ port, contextId }) => /* @__PURE__ */ jsxs12("div", { className: "szenen-setup", "data-testid": "bereich-setup", children: [
9430
- /* @__PURE__ */ jsx12("p", { className: "szenen-area__lead", children: "Scene Setups und Camera Rigs dieses Kontexts." }),
9829
+ /* @__PURE__ */ jsx12("p", { className: "szenen-area__lead", children: "Bildaufbauten, Kameras und Stile dieses Kontexts." }),
9431
9830
  /* @__PURE__ */ jsx12(
9432
9831
  ElementsArea,
9433
9832
  {
9434
9833
  port,
9435
9834
  contextId,
9436
9835
  restrictToTypes: ["scene_setup", "camera_preset", "camera_pattern", "style"],
9437
- allTypesLabel: "alle Bildaufbau-Typen"
9836
+ allTypesLabel: "alle Bildaufbau-Typen",
9837
+ listTitle: "Bildaufbau"
9438
9838
  }
9439
9839
  )
9440
9840
  ] });
@@ -9442,34 +9842,35 @@ var SetupArea = ({ port, contextId }) => /* @__PURE__ */ jsxs12("div", { classNa
9442
9842
  // src/features/szenen/areas/ShotArea.tsx
9443
9843
  import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
9444
9844
  var ShotArea = ({ port, contextId }) => /* @__PURE__ */ jsxs13("div", { className: "szenen-shot", "data-testid": "bereich-shot", children: [
9445
- /* @__PURE__ */ jsx13("p", { className: "szenen-area__lead", children: "Shots dieses Kontexts. Auswahl zeigt Runden und startet Prompt-L\xE4ufe." }),
9845
+ /* @__PURE__ */ jsx13("p", { className: "szenen-area__lead", children: "Prompts dieses Kontexts. Auswahl zeigt Runden und startet Prompt-L\xE4ufe." }),
9446
9846
  /* @__PURE__ */ jsx13(
9447
9847
  ElementsArea,
9448
9848
  {
9449
9849
  port,
9450
9850
  contextId,
9451
9851
  restrictToTypes: ["shot", "shot_concept", "target_model"],
9452
- allTypesLabel: "alle Prompt-Typen"
9852
+ allTypesLabel: "alle Prompt-Typen",
9853
+ listTitle: "Prompts"
9453
9854
  }
9454
9855
  )
9455
9856
  ] });
9456
9857
 
9457
9858
  // src/features/szenen/areas/MediaArea.tsx
9458
- import { useState as useState11 } from "react";
9859
+ import { useState as useState12 } from "react";
9459
9860
  import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
9460
9861
  var leer = async () => ({ kind: "ok", value: [] });
9461
9862
  var MediaArea = ({ port }) => {
9462
9863
  const media = port.media;
9463
- const [versionInput, setVersionInput] = useState11("");
9464
- const [versionId, setVersionId] = useState11("");
9465
- const [itemInput, setItemInput] = useState11("");
9466
- const [itemId, setItemId] = useState11("");
9467
- const [assetId, setAssetId] = useState11("");
9468
- const [role, setRole] = useState11("reference");
9469
- const [position, setPosition] = useState11("0");
9470
- const [notiz, setNotiz] = useState11(null);
9471
- const [busy, setBusy] = useState11(false);
9472
- const [refresh, setRefresh] = useState11(0);
9864
+ const [versionInput, setVersionInput] = useState12("");
9865
+ const [versionId, setVersionId] = useState12("");
9866
+ const [itemInput, setItemInput] = useState12("");
9867
+ const [itemId, setItemId] = useState12("");
9868
+ const [assetId, setAssetId] = useState12("");
9869
+ const [role, setRole] = useState12("reference");
9870
+ const [position, setPosition] = useState12("0");
9871
+ const [notiz, setNotiz] = useState12(null);
9872
+ const [busy, setBusy] = useState12(false);
9873
+ const [refresh, setRefresh] = useState12(0);
9473
9874
  const [versionPhase] = usePortQuery(
9474
9875
  () => versionId ? media.listVersionMedia(versionId) : leer(),
9475
9876
  [media, versionId, refresh]
@@ -9595,24 +9996,24 @@ var MediaArea = ({ port }) => {
9595
9996
  };
9596
9997
 
9597
9998
  // src/features/szenen/areas/DeriveArea.tsx
9598
- import { useRef as useRef2, useState as useState14 } from "react";
9999
+ import { useEffect as useEffect5, useMemo as useMemo3, useRef as useRef2, useState as useState15 } from "react";
9599
10000
 
9600
10001
  // src/features/szenen/areas/RecoveryPanel.tsx
9601
- import { useState as useState12 } from "react";
9602
- import { Fragment as Fragment4, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
10002
+ import { useState as useState13 } from "react";
10003
+ import { Fragment as Fragment5, jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
9603
10004
  var Diagnosen = ({ befunde, testId }) => {
9604
10005
  if (befunde.length === 0) return null;
9605
10006
  return /* @__PURE__ */ jsx15("ul", { className: "szenen-diagnose__liste", "data-testid": testId, children: befunde.map((d, i) => /* @__PURE__ */ jsxs15("li", { "data-severity": d.severity, children: [
9606
10007
  /* @__PURE__ */ jsx15("code", { children: d.code }),
9607
- d.proposal_type && /* @__PURE__ */ jsxs15(Fragment4, { children: [
10008
+ d.proposal_type && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9608
10009
  " \xB7 ",
9609
10010
  /* @__PURE__ */ jsx15("strong", { children: d.proposal_type })
9610
10011
  ] }),
9611
- d.pointer && /* @__PURE__ */ jsxs15(Fragment4, { children: [
10012
+ d.pointer && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9612
10013
  " \xB7 ",
9613
10014
  /* @__PURE__ */ jsx15("code", { children: d.pointer })
9614
10015
  ] }),
9615
- typeof d.line === "number" && /* @__PURE__ */ jsxs15(Fragment4, { children: [
10016
+ typeof d.line === "number" && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9616
10017
  " \xB7 Zeile ",
9617
10018
  d.line,
9618
10019
  ", Spalte ",
@@ -9627,7 +10028,7 @@ var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs15("div", { className: "sz
9627
10028
  bewertung.status === "partial" && "Diese Fassung ist teilweise verwertbar \u2014 nicht alles kommt durch.",
9628
10029
  bewertung.status === "invalid" && "Aus dieser Fassung ist nichts zu \xFCbernehmen."
9629
10030
  ] }),
9630
- bewertung.proposals.length > 0 && /* @__PURE__ */ jsxs15(Fragment4, { children: [
10031
+ bewertung.proposals.length > 0 && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9631
10032
  /* @__PURE__ */ jsx15("h5", { children: "Verwertbar" }),
9632
10033
  /* @__PURE__ */ jsx15("ul", { "data-testid": "rettung-verwertbar", children: bewertung.proposals.map((p) => /* @__PURE__ */ jsxs15("li", { "data-testid": `rettung-verwertbar-${p.type}`, children: [
9633
10034
  /* @__PURE__ */ jsx15("strong", { children: p.type }),
@@ -9640,7 +10041,7 @@ var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs15("div", { className: "sz
9640
10041
  ] }, i)) })
9641
10042
  ] }, p.type)) })
9642
10043
  ] }),
9643
- bewertung.rejected.length > 0 && /* @__PURE__ */ jsxs15(Fragment4, { children: [
10044
+ bewertung.rejected.length > 0 && /* @__PURE__ */ jsxs15(Fragment5, { children: [
9644
10045
  /* @__PURE__ */ jsx15("h5", { children: "Nicht verwertbar" }),
9645
10046
  /* @__PURE__ */ jsx15("ul", { "data-testid": "rettung-abgelehnt", children: bewertung.rejected.map((r) => /* @__PURE__ */ jsxs15("li", { "data-testid": `rettung-abgelehnt-${r.type}`, children: [
9646
10047
  /* @__PURE__ */ jsx15("strong", { children: r.type }),
@@ -9649,11 +10050,11 @@ var Ausbeute = ({ bewertung }) => /* @__PURE__ */ jsxs15("div", { className: "sz
9649
10050
  ] })
9650
10051
  ] });
9651
10052
  var RecoveryPanel = ({ port, lauf }) => {
9652
- const [arbeitskopie, setArbeitskopie] = useState12(null);
9653
- const [bewertung, setBewertung] = useState12(null);
9654
- const [gesichert, setGesichert] = useState12(null);
9655
- const [meldung, setMeldung] = useState12(null);
9656
- const [laeuft, setLaeuft] = useState12(false);
10053
+ const [arbeitskopie, setArbeitskopie] = useState13(null);
10054
+ const [bewertung, setBewertung] = useState13(null);
10055
+ const [gesichert, setGesichert] = useState13(null);
10056
+ const [meldung, setMeldung] = useState13(null);
10057
+ const [laeuft, setLaeuft] = useState13(false);
9657
10058
  if (!port.derivation) return null;
9658
10059
  if (typeof lauf.raw_output !== "string" || lauf.raw_output.length === 0) return null;
9659
10060
  const derivation = port.derivation;
@@ -9776,12 +10177,12 @@ var RecoveryPanel = ({ port, lauf }) => {
9776
10177
  };
9777
10178
 
9778
10179
  // src/features/szenen/areas/ChainActions.tsx
9779
- import { useState as useState13 } from "react";
9780
- import { Fragment as Fragment5, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
10180
+ import { useState as useState14 } from "react";
10181
+ import { Fragment as Fragment6, jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
9781
10182
  var ChainActions = ({ port, runId, recoveryId }) => {
9782
- const [graph, setGraph] = useState13(null);
9783
- const [meldung, setMeldung] = useState13(null);
9784
- const [laeuft, setLaeuft] = useState13(false);
10183
+ const [graph, setGraph] = useState14(null);
10184
+ const [meldung, setMeldung] = useState14(null);
10185
+ const [laeuft, setLaeuft] = useState14(false);
9785
10186
  if (!port.derivation) return null;
9786
10187
  const derivation = port.derivation;
9787
10188
  const runs = port.runs;
@@ -9845,23 +10246,29 @@ var ChainActions = ({ port, runId, recoveryId }) => {
9845
10246
  ] }, m.type)) })
9846
10247
  ] })
9847
10248
  ] }),
9848
- shotKnoten && /* @__PURE__ */ jsxs16(Fragment5, { children: [
10249
+ shotKnoten && /* @__PURE__ */ jsxs16(Fragment6, { children: [
9849
10250
  /* @__PURE__ */ jsx16("p", { children: 'Die Entw\xFCrfe lassen sich jetzt unter \u201E1 \xB7 Bausteine" \xE4ndern. Der Prompt-Lauf friert den Stand ein, den er dabei vorfindet \u2014 dieselbe Aktion steht auch am Shot selbst, unter \u201E4 \xB7 Prompt".' }),
9850
- /* @__PURE__ */ jsx16(ChainPromptAction, { port, shotElementId: shotKnoten.elementId })
10251
+ /* @__PURE__ */ jsx16(
10252
+ PromptStartAction,
10253
+ {
10254
+ port,
10255
+ source: { kind: "draft_chain", shotElementId: shotKnoten.elementId }
10256
+ }
10257
+ )
9851
10258
  ] }),
9852
10259
  meldung && /* @__PURE__ */ jsx16("p", { className: "szenen-error", role: "alert", "data-testid": "kette-meldung", children: meldung })
9853
10260
  ] });
9854
10261
  };
9855
10262
 
9856
10263
  // src/features/szenen/areas/DeriveArea.tsx
9857
- import { Fragment as Fragment6, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
10264
+ import { Fragment as Fragment7, jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
9858
10265
  var MODUS_TEXT = {
9859
10266
  prompt: "Nur Prompt",
9860
10267
  image: "Nur Bild",
9861
10268
  image_prompt: "Bild und Prompt"
9862
10269
  };
9863
10270
  var BelegFeld = ({ titel, text, testId, offen }) => {
9864
- const [kopiert, setKopiert] = useState14(false);
10271
+ const [kopiert, setKopiert] = useState15(false);
9865
10272
  const feld = useRef2(null);
9866
10273
  async function kopieren() {
9867
10274
  try {
@@ -9957,14 +10364,64 @@ function readAsBase642(datei) {
9957
10364
  leser.readAsDataURL(datei);
9958
10365
  });
9959
10366
  }
10367
+ function useVorschauen(port, mediaRefs) {
10368
+ const [quellen, setQuellen] = useState15(() => /* @__PURE__ */ new Map());
10369
+ const gehalten = useRef2(/* @__PURE__ */ new Map());
10370
+ const schluessel = mediaRefs.join(" ");
10371
+ useEffect5(() => {
10372
+ const bestand = port.imageLibrary;
10373
+ if (!bestand?.loadPreview) return void 0;
10374
+ const refs = schluessel ? schluessel.split(" ") : [];
10375
+ const lauf = { abgebrochen: false };
10376
+ void ladeVorschauen(
10377
+ bestand,
10378
+ refs,
10379
+ (mediaRef, quelle) => {
10380
+ gehalten.current.set(mediaRef, quelle);
10381
+ setQuellen(new Map(gehalten.current));
10382
+ },
10383
+ { parallel: 4, hat: (ref) => gehalten.current.has(ref), lauf }
10384
+ );
10385
+ return () => {
10386
+ lauf.abgebrochen = true;
10387
+ };
10388
+ }, [port, schluessel]);
10389
+ return quellen;
10390
+ }
10391
+ var Kachel = ({ quelle, alt }) => /* @__PURE__ */ jsx17("span", { className: "szenen-bildkachel", children: quelle ? /* @__PURE__ */ jsx17("img", { src: quelle, alt, loading: "lazy" }) : /* @__PURE__ */ jsx17("span", { className: "szenen-bildkachel__leer", "aria-hidden": "true" }) });
9960
10392
  var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
9961
- const [suche, setSuche] = useState14("");
9962
- const [bilder] = usePortQuery(
9963
- () => port.imageLibrary.listImages({ search: suche.trim() || void 0, limit: 60 }),
10393
+ const [suche, setSuche] = useState15("");
10394
+ const [offenesWerk, setOffenesWerk] = useState15(null);
10395
+ const [items] = usePortQuery(
10396
+ () => port.imageLibrary.listItems({ search: suche.trim() || void 0, limit: 60 }),
9964
10397
  [port, suche]
9965
10398
  );
10399
+ const werk = items.status === "ready" ? items.value.find((i) => i.itemRef === offenesWerk) ?? null : null;
10400
+ const sichtbar = useMemo3(() => {
10401
+ const refs = werk ? werk.images.map((b) => b.mediaRef) : items.status === "ready" ? items.value.map((i) => i.images[0]?.mediaRef).filter((r) => Boolean(r)) : [];
10402
+ return [.../* @__PURE__ */ new Set([...refs, ...gewaehlt.map((b) => b.mediaRef)])];
10403
+ }, [items, werk, gewaehlt]);
10404
+ const quellen = useVorschauen(port, sichtbar);
10405
+ const quelleVon = (bild) => bild.thumbUrl || quellen.get(bild.mediaRef) || null;
9966
10406
  return /* @__PURE__ */ jsxs17("div", { className: "szenen-bildwahl", "data-testid": "bildwahl", children: [
9967
- /* @__PURE__ */ jsxs17("label", { className: "szenen-field", children: [
10407
+ werk ? /* @__PURE__ */ jsxs17("div", { className: "szenen-bildwahl__kopf", children: [
10408
+ /* @__PURE__ */ jsx17(
10409
+ "button",
10410
+ {
10411
+ type: "button",
10412
+ className: "szenen-bildwahl__zurueck",
10413
+ onClick: () => setOffenesWerk(null),
10414
+ "data-testid": "bildwahl-zurueck",
10415
+ children: "Zurueck zur Auswahl"
10416
+ }
10417
+ ),
10418
+ /* @__PURE__ */ jsxs17("span", { className: "szenen-bildwahl__werktitel", "data-testid": "bildwahl-werktitel", children: [
10419
+ werk.title,
10420
+ " \xB7 ",
10421
+ werk.images.length,
10422
+ " Bilder"
10423
+ ] })
10424
+ ] }) : /* @__PURE__ */ jsxs17("label", { className: "szenen-field", children: [
9968
10425
  /* @__PURE__ */ jsx17("span", { children: "Bild aus dem Bestand" }),
9969
10426
  /* @__PURE__ */ jsx17(
9970
10427
  "input",
@@ -9972,31 +10429,70 @@ var BildWaehler = ({ port, gewaehlt, onWaehlen, onEntfernen }) => {
9972
10429
  type: "search",
9973
10430
  value: suche,
9974
10431
  onChange: (e) => setSuche(e.target.value),
10432
+ onKeyDown: (e) => {
10433
+ if (e.key === "Enter") e.preventDefault();
10434
+ },
9975
10435
  placeholder: "Suchen \u2026",
9976
10436
  "data-testid": "bild-suche"
9977
10437
  }
9978
10438
  )
9979
10439
  ] }),
9980
- bilder.status === "loading" && /* @__PURE__ */ jsx17("p", { children: "Bilder werden geladen \u2026" }),
9981
- bilder.status === "error" && /* @__PURE__ */ jsxs17("p", { className: "szenen-error", role: "alert", children: [
10440
+ items.status === "loading" && /* @__PURE__ */ jsx17("p", { children: "Bilder werden geladen \u2026" }),
10441
+ items.status === "error" && /* @__PURE__ */ jsxs17("p", { className: "szenen-error", role: "alert", children: [
9982
10442
  "Der Bildbestand ist nicht lesbar: ",
9983
- bilder.message
10443
+ items.message
9984
10444
  ] }),
9985
- bilder.status === "ready" && bilder.value.length === 0 && /* @__PURE__ */ jsx17("p", { className: "szenen-empty", "data-testid": "bildwahl-leer", children: "Zu dieser Suche gibt es kein Bild. Ohne Treffer bleibt der Upload." }),
9986
- bilder.status === "ready" && bilder.value.length > 0 && /* @__PURE__ */ jsx17("ul", { className: "szenen-bildwahl__liste", children: bilder.value.map((bild) => /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs17(
10445
+ items.status === "ready" && items.value.length === 0 && /* @__PURE__ */ jsx17("p", { className: "szenen-empty", "data-testid": "bildwahl-leer", children: "Zu dieser Suche gibt es kein Bild. Ohne Treffer bleibt der Upload." }),
10446
+ werk && /* @__PURE__ */ jsx17("ul", { className: "szenen-bildwahl__raster", "data-testid": "bildwahl-galerie", children: werk.images.map((bild, position) => /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs17(
9987
10447
  "button",
9988
10448
  {
9989
10449
  type: "button",
9990
- onClick: () => onWaehlen(bild),
10450
+ onClick: () => {
10451
+ onWaehlen(bild);
10452
+ setOffenesWerk(null);
10453
+ },
9991
10454
  "data-testid": `bild-waehlen-${bild.mediaRef}`,
10455
+ title: bild.title,
9992
10456
  children: [
9993
- bild.thumbUrl && /* @__PURE__ */ jsx17("img", { src: bild.thumbUrl, alt: "" }),
9994
- /* @__PURE__ */ jsx17("span", { children: bild.title })
10457
+ /* @__PURE__ */ jsx17(Kachel, { quelle: quelleVon(bild), alt: bild.title }),
10458
+ /* @__PURE__ */ jsxs17("span", { className: "szenen-bildwahl__nummer", children: [
10459
+ "#",
10460
+ position + 1
10461
+ ] })
9995
10462
  ]
9996
10463
  }
9997
10464
  ) }, bild.mediaRef)) }),
10465
+ !werk && items.status === "ready" && items.value.length > 0 && /* @__PURE__ */ jsx17("ul", { className: "szenen-bildwahl__raster", "data-testid": "bildwahl-werke", children: items.value.map((item) => {
10466
+ const deckbild = item.images[0];
10467
+ if (!deckbild) return null;
10468
+ return /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsxs17(
10469
+ "button",
10470
+ {
10471
+ type: "button",
10472
+ onClick: () => item.images.length === 1 ? onWaehlen(deckbild) : setOffenesWerk(item.itemRef),
10473
+ "data-testid": `item-waehlen-${item.itemRef}`,
10474
+ title: item.title,
10475
+ children: [
10476
+ /* @__PURE__ */ jsx17(Kachel, { quelle: quelleVon(deckbild), alt: item.title }),
10477
+ item.images.length > 1 && /* @__PURE__ */ jsxs17(
10478
+ "span",
10479
+ {
10480
+ className: "szenen-bildwahl__anzahl",
10481
+ "data-testid": `item-anzahl-${item.itemRef}`,
10482
+ children: [
10483
+ item.images.length,
10484
+ "x"
10485
+ ]
10486
+ }
10487
+ ),
10488
+ /* @__PURE__ */ jsx17("span", { className: "szenen-bildwahl__titel", children: item.title })
10489
+ ]
10490
+ }
10491
+ ) }, item.itemRef);
10492
+ }) }),
9998
10493
  gewaehlt.length > 0 && /* @__PURE__ */ jsx17("ul", { className: "szenen-bildwahl__gewaehlt", "data-testid": "bilder-gewaehlt", children: gewaehlt.map((bild) => /* @__PURE__ */ jsxs17("li", { children: [
9999
- bild.title,
10494
+ /* @__PURE__ */ jsx17(Kachel, { quelle: quelleVon(bild), alt: bild.title }),
10495
+ /* @__PURE__ */ jsx17("span", { className: "szenen-bildwahl__titel", children: bild.title }),
10000
10496
  /* @__PURE__ */ jsx17(
10001
10497
  "button",
10002
10498
  {
@@ -10016,26 +10512,29 @@ async function digestOf(datei) {
10016
10512
  return [...new Uint8Array(hash)].map((b) => b.toString(16).padStart(2, "0")).join("");
10017
10513
  }
10018
10514
  var DeriveArea = ({ port, contextId }) => {
10019
- const [policyVersionId, setPolicyVersionId] = useState14("");
10020
- const [modus, setModus] = useState14("prompt");
10021
- const [promptText, setPromptText] = useState14("");
10022
- const [dateien, setDateien] = useState14([]);
10023
- const [bestandsbilder, setBestandsbilder] = useState14([]);
10024
- const [laeuft, setLaeuft] = useState14(false);
10025
- const [lauf, setLauf] = useState14(null);
10026
- const [meldung, setMeldung] = useState14(null);
10027
- const [uebernommen, setUebernommen] = useState14({});
10028
- const [titel, setTitel] = useState14({});
10029
- const [referenzen, setReferenzen] = useState14({});
10030
- const [beanstandung, setBeanstandung] = useState14(null);
10031
- const [zusatz, setZusatz] = useState14("");
10515
+ const [policyVersionId, setPolicyVersionId] = useState15("");
10516
+ const [modus, setModus] = useState15("prompt");
10517
+ const [promptText, setPromptText] = useState15("");
10518
+ const [dateien, setDateien] = useState15([]);
10519
+ const [bestandsbilder, setBestandsbilder] = useState15([]);
10520
+ const [laeuft, setLaeuft] = useState15(false);
10521
+ const [lauf, setLauf] = useState15(null);
10522
+ const [meldung, setMeldung] = useState15(null);
10523
+ const [uebernommen, setUebernommen] = useState15({});
10524
+ const [titel, setTitel] = useState15({});
10525
+ const [referenzen, setReferenzen] = useState15({});
10526
+ const [beanstandung, setBeanstandung] = useState15(null);
10527
+ const [zusatz, setZusatz] = useState15("");
10032
10528
  const [regeln] = usePortQuery(
10033
10529
  () => port.derivation.listPolicies(contextId),
10034
10530
  [port, contextId]
10035
10531
  );
10036
10532
  const gewaehlt = regeln.status === "ready" ? regeln.value.find((r) => r.versionId === policyVersionId) ?? null : null;
10037
10533
  async function starten(folgt) {
10038
- if (!gewaehlt) return;
10534
+ if (!gewaehlt) {
10535
+ setMeldung("Bitte zuerst eine Rekonstruktionsregel waehlen \u2014 ohne sie ist kein Lauf reproduzierbar (D-03).");
10536
+ return;
10537
+ }
10039
10538
  setLaeuft(true);
10040
10539
  setMeldung(null);
10041
10540
  setLauf(null);
@@ -10242,7 +10741,7 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
10242
10741
  }
10243
10742
  )
10244
10743
  ] }),
10245
- modus !== "prompt" && /* @__PURE__ */ jsxs17(Fragment6, { children: [
10744
+ modus !== "prompt" && /* @__PURE__ */ jsxs17(Fragment7, { children: [
10246
10745
  port.imageLibrary && /* @__PURE__ */ jsx17(
10247
10746
  BildWaehler,
10248
10747
  {
@@ -10344,7 +10843,7 @@ ${teile.map((t) => `- ${t}`).join("\n")}`;
10344
10843
  )
10345
10844
  ] }),
10346
10845
  /* @__PURE__ */ jsx17("pre", { className: "szenen-proposal__payload", children: JSON.stringify(vorschlag.payload, null, 2) }),
10347
- bezug && !fertig && /* @__PURE__ */ jsxs17(Fragment6, { children: [
10846
+ bezug && !fertig && /* @__PURE__ */ jsxs17(Fragment7, { children: [
10348
10847
  /* @__PURE__ */ jsx17(
10349
10848
  ReferencePicker,
10350
10849
  {
@@ -10412,9 +10911,9 @@ var SzenenView = ({
10412
10911
  initialArea,
10413
10912
  onAreaChange
10414
10913
  }) => {
10415
- const bereiche = useMemo3(() => areasFor(port), [port]);
10416
- const faehig = useMemo3(() => capabilitiesOf(port), [port]);
10417
- const [aktiv, setAktiv] = useState15(() => resolveArea(port, initialArea));
10914
+ const bereiche = useMemo4(() => areasFor(port), [port]);
10915
+ const faehig = useMemo4(() => capabilitiesOf(port), [port]);
10916
+ const [aktiv, setAktiv] = useState16(() => resolveArea(port, initialArea));
10418
10917
  const wechsle = (id) => {
10419
10918
  setAktiv(id);
10420
10919
  onAreaChange?.(id);
@@ -10445,7 +10944,16 @@ var SzenenView = ({
10445
10944
  )) }),
10446
10945
  /* @__PURE__ */ jsxs18("section", { className: "szenen-view__area", "aria-label": aktuellerBereich.title, children: [
10447
10946
  aktiv === "derive" && port.derivation && /* @__PURE__ */ jsx18(DeriveArea, { port, contextId }),
10448
- aktiv === "elements" && /* @__PURE__ */ jsx18(ElementsArea, { port, contextId }),
10947
+ aktiv === "elements" && /* @__PURE__ */ jsx18(
10948
+ ElementsArea,
10949
+ {
10950
+ port,
10951
+ contextId,
10952
+ restrictToTypes: BAUSTEIN_TYPES,
10953
+ allTypesLabel: "alle Bausteine",
10954
+ listTitle: "Bausteine"
10955
+ }
10956
+ ),
10449
10957
  aktiv === "scene" && /* @__PURE__ */ jsx18(SceneArea, { port, contextId }),
10450
10958
  aktiv === "setup" && /* @__PURE__ */ jsx18(SetupArea, { port, contextId }),
10451
10959
  aktiv === "shot" && /* @__PURE__ */ jsx18(ShotArea, { port, contextId }),
@@ -10460,6 +10968,17 @@ var SzenenView = ({
10460
10968
  };
10461
10969
 
10462
10970
  // src/lib/szenen/flowTextGenerationPort.ts
10971
+ function alsFlowTextZugang(sdk) {
10972
+ return async (prompt, options) => {
10973
+ const antwort = await sdk(prompt, options);
10974
+ if (typeof antwort?.text !== "string") {
10975
+ throw new Error(
10976
+ `Flow.generate.text lieferte kein { text: string }, sondern ${antwort === null || antwort === void 0 ? String(antwort) : typeof antwort}: ${JSON.stringify(antwort)?.slice(0, 200)}`
10977
+ );
10978
+ }
10979
+ return antwort.text;
10980
+ };
10981
+ }
10463
10982
  function createFlowTextGenerationPort(generateText, options = {}) {
10464
10983
  const provider = options.provider ?? "flow";
10465
10984
  const modelId = options.modelId ?? "flow.generate.text";
@@ -11226,7 +11745,7 @@ var CHAIN_EDGES = {
11226
11745
  scene_ref: { from: "scene_setup", to: "scene" },
11227
11746
  scene_setup_ref: { from: "shot", to: "scene_setup" }
11228
11747
  };
11229
- function istText3(wert) {
11748
+ function istText4(wert) {
11230
11749
  return typeof wert === "string" && wert.trim().length > 0;
11231
11750
  }
11232
11751
  function checkDraftChainMeta(meta, type) {
@@ -11237,14 +11756,14 @@ function checkDraftChainMeta(meta, type) {
11237
11756
  };
11238
11757
  }
11239
11758
  const m = meta;
11240
- if (!istText3(m.chain_id)) return { ok: false, message: '"chain_id" fehlt oder ist leer.' };
11241
- if (!istText3(m.source_run_id)) {
11759
+ if (!istText4(m.chain_id)) return { ok: false, message: '"chain_id" fehlt oder ist leer.' };
11760
+ if (!istText4(m.source_run_id)) {
11242
11761
  return {
11243
11762
  ok: false,
11244
11763
  message: '"source_run_id" fehlt oder ist leer \u2014 ohne sie ist die Herkunft eines Kettenknotens nicht rekonstruierbar (D-96/B3).'
11245
11764
  };
11246
11765
  }
11247
- if (m.source_recovery_id !== void 0 && !istText3(m.source_recovery_id)) {
11766
+ if (m.source_recovery_id !== void 0 && !istText4(m.source_recovery_id)) {
11248
11767
  return { ok: false, message: '"source_recovery_id" ist gesetzt, aber leer.' };
11249
11768
  }
11250
11769
  if (!Array.isArray(m.links)) {
@@ -11269,7 +11788,7 @@ function checkDraftChainMeta(meta, type) {
11269
11788
  message: `"${l.field}" gehoert an einen ${kante.from}, nicht an einen ${type}.`
11270
11789
  };
11271
11790
  }
11272
- if (!istText3(l.target_element_id) || !istText3(l.target_draft_id)) {
11791
+ if (!istText4(l.target_element_id) || !istText4(l.target_draft_id)) {
11273
11792
  return {
11274
11793
  ok: false,
11275
11794
  message: `"links[${index}]" braucht target_element_id und target_draft_id.`
@@ -11917,12 +12436,12 @@ function createHfEventChannel(options) {
11917
12436
  // src/lib/szenen/resolve.ts
11918
12437
  var ResolveTechnicalError = class extends Error {
11919
12438
  };
11920
- var isObject10 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
11921
- var asArray2 = (v) => Array.isArray(v) ? v : [];
12439
+ var isObject11 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
12440
+ var asArray3 = (v) => Array.isArray(v) ? v : [];
11922
12441
  var str = (v) => typeof v === "string" ? v : null;
11923
12442
  var num = (v) => typeof v === "number" ? v : null;
11924
12443
  async function refOf(resolver, ref, expected, path) {
11925
- const versionId = isObject10(ref) ? str(ref.version_id) : null;
12444
+ const versionId = isObject11(ref) ? str(ref.version_id) : null;
11926
12445
  if (!versionId) {
11927
12446
  return {
11928
12447
  ok: false,
@@ -11974,8 +12493,11 @@ async function refOf(resolver, ref, expected, path) {
11974
12493
  }
11975
12494
  return { ok: true, version };
11976
12495
  }
12496
+ function ausgelassen(diagnostics, code, path, message) {
12497
+ diagnostics.push({ code, origin: "resolution", path, message });
12498
+ }
11977
12499
  function entraeumlichtePlatzierung(placement, assumptions) {
11978
- if (!isObject10(placement)) return null;
12500
+ if (!isObject11(placement)) return null;
11979
12501
  if (placement.mode !== "pattern") {
11980
12502
  assumptions.push(
11981
12503
  `Die Kameraplatzierung (mode "${str(placement.mode) ?? "unbekannt"}") ist metrisch und entfaellt ohne can_place. Der Renderer darf daraus keine Position ableiten.`
@@ -11990,7 +12512,7 @@ function entraeumlichtePlatzierung(placement, assumptions) {
11990
12512
  const entfallen = [];
11991
12513
  if (placement.offsets !== void 0) entfallen.push("offsets");
11992
12514
  const height = placement.height;
11993
- if (isObject10(height)) {
12515
+ if (isObject11(height)) {
11994
12516
  if (height.mode === "anchor") {
11995
12517
  const behalteneHoehe = {
11996
12518
  mode: "anchor",
@@ -12069,142 +12591,328 @@ async function resolveShotPayload(input) {
12069
12591
  chain
12070
12592
  } = input;
12071
12593
  const assumptions = [];
12072
- const shotVersion = {
12073
- version_id: shotVersionId,
12074
- element_id: shotElementId,
12075
- payload: shotPayload
12076
- };
12077
- const shotErrors = ohneKettenReferenz(
12078
- validatePayload("shot", shotVersion.payload).errors,
12079
- chain ? "scene_setup_ref" : null
12080
- );
12081
- if (shotErrors.length > 0) {
12594
+ const diagnostics = [];
12595
+ if (!isObject11(shotPayload)) {
12082
12596
  return {
12083
12597
  kind: "rejected",
12084
12598
  failure: {
12085
12599
  class: "schema",
12086
12600
  where: "shot",
12087
- message: `Die Shot-Payload verletzt das Schema (${shotErrors.length} Befunde). Es wurde keine ihrer Referenzen aufgeloest.`,
12088
- errors: shotErrors
12601
+ message: `Die Shot-Payload ist kein Objekt, sondern ${Array.isArray(shotPayload) ? "ein Array" : typeof shotPayload}. Daraus laesst sich kein Auftrag herstellen.`,
12602
+ errors: []
12603
+ }
12604
+ };
12605
+ }
12606
+ const shot = shotPayload;
12607
+ for (const fehler4 of ohneKettenReferenz(
12608
+ validatePayload("shot", shotPayload).errors,
12609
+ chain ? "scene_setup_ref" : null
12610
+ )) {
12611
+ diagnostics.push(diagnosticOfSchemaError(fehler4, `Shot ${shotElementId}`));
12612
+ }
12613
+ let setup = null;
12614
+ let report = null;
12615
+ let canPlace = false;
12616
+ let capabilities;
12617
+ let scene;
12618
+ const nenntSetup = chain !== void 0 || shot.scene_setup_ref !== void 0;
12619
+ if (!nenntSetup) {
12620
+ return {
12621
+ kind: "rejected",
12622
+ failure: {
12623
+ class: "no_content",
12624
+ message: `Der Shot ${shotElementId} nennt kein scene_setup_ref und fuehrt keine Draft-Kette. Ohne Setup gibt es keinen Weg zu einer Szene und damit keinen beschreibbaren Inhalt.`
12089
12625
  }
12090
12626
  };
12091
12627
  }
12092
- const shot = shotVersion.payload;
12093
12628
  const setupRef = chain ? { ok: true, version: chain.setup } : await refOf(resolver, shot.scene_setup_ref, "scene_setup", "/scene_setup_ref");
12094
12629
  if (!setupRef.ok) return { kind: "rejected", failure: setupRef.failure };
12095
- const setupErrors = ohneKettenReferenz(
12096
- validatePayload("scene_setup", setupRef.version.payload).errors,
12097
- chain ? "scene_ref" : null
12098
- );
12099
- if (setupErrors.length > 0) {
12630
+ if (!isObject11(setupRef.version.payload)) {
12100
12631
  return {
12101
12632
  kind: "rejected",
12102
12633
  failure: {
12103
12634
  class: "schema",
12104
12635
  where: "scene_setup",
12105
- message: `Die Scene-Setup-Payload verletzt das Schema (${setupErrors.length} Befunde). Weder ihre Referenzen noch der Faehigkeitsbericht wurden mit einem Resolver gefahren.`,
12106
- errors: setupErrors
12636
+ message: `Die Scene-Setup-Payload ist kein Objekt, sondern ${Array.isArray(setupRef.version.payload) ? "ein Array" : typeof setupRef.version.payload}.`,
12637
+ errors: []
12107
12638
  }
12108
12639
  };
12109
12640
  }
12110
- const setup = setupRef.version.payload;
12111
- const report = await capabilityReport({
12641
+ setup = {
12642
+ element_id: setupRef.version.element_id,
12643
+ version_id: setupRef.version.version_id,
12644
+ payload: setupRef.version.payload
12645
+ };
12646
+ report = await capabilityReport({
12112
12647
  type: "scene_setup",
12113
- setupPayload: setup,
12114
- elementId: setupRef.version.element_id,
12648
+ setupPayload: setup.payload,
12649
+ elementId: setup.element_id,
12115
12650
  resolver,
12116
12651
  // Bei einer Draft-Kette kommt die Szene von hier, nicht aus `scene_ref`
12117
12652
  // (C1). Dasselbe Regelwerk, ein anderer Weg zur selben Szene.
12118
12653
  ...chain ? { chainScene: chain.scene.payload } : {}
12119
12654
  });
12120
- const gate = capabilityGate(report, "can_render_prompt");
12121
- if (gate) return { kind: "rejected", failure: gate };
12122
- const placeGate = capabilityGate(report, "can_place");
12123
- if (placeGate && placeGate.class === "capability_undetermined") {
12124
- return { kind: "rejected", failure: placeGate };
12125
- }
12126
- const canPlace = report.can_place.state === "yes";
12655
+ diagnostics.push(...report.promptDiagnostics);
12656
+ canPlace = report.can_place.state === "yes";
12127
12657
  if (!canPlace) {
12128
12658
  assumptions.push(
12129
- "can_place ist nicht erfuellt \u2014 alle Platzierungen bleiben null. Der Renderer darf daraus keine Koordinaten ableiten (D-47)."
12659
+ `can_place ist "${report.can_place.state}" \u2014 alle Platzierungen bleiben null. Der Renderer darf daraus keine Koordinaten ableiten (D-47).`
12130
12660
  );
12131
12661
  }
12132
- const sceneRef = chain ? { ok: true, version: chain.scene } : await refOf(resolver, setup.scene_ref, "scene", "/scene_ref");
12662
+ capabilities = {
12663
+ can_describe_scene: report.can_describe_scene.state,
12664
+ can_render_prompt: report.can_render_prompt.state,
12665
+ can_place: report.can_place.state
12666
+ };
12667
+ const sceneRef = chain ? { ok: true, version: chain.scene } : await refOf(resolver, setup.payload.scene_ref, "scene", "/scene_ref");
12133
12668
  if (!sceneRef.ok) return { kind: "rejected", failure: sceneRef.failure };
12134
- const scene = sceneRef.version.payload;
12135
- const cameraId = str(shot.camera_id) ?? "";
12136
- const rig = isObject10(setup.camera_rig) ? setup.camera_rig : {};
12137
- const cameras = asArray2(rig.cameras);
12138
- const cameraIndex = cameras.findIndex(
12139
- (camera2) => isObject10(camera2) && camera2.camera_id === cameraId
12140
- );
12141
- if (cameraIndex < 0) {
12669
+ if (!isObject11(sceneRef.version.payload)) {
12142
12670
  return {
12143
12671
  kind: "rejected",
12144
12672
  failure: {
12145
- class: "reference_unresolvable",
12146
- message: `Die aktive camera_id "${cameraId}" kommt im Rig der Scene-Setup-Version ${setupRef.version.version_id} nicht vor (P-01).`,
12147
- versionId: setupRef.version.version_id,
12148
- path: "/camera_id",
12149
- reason: "unknown"
12673
+ class: "schema",
12674
+ where: "scene",
12675
+ message: `Die Szenen-Payload ist kein Objekt, sondern ${Array.isArray(sceneRef.version.payload) ? "ein Array" : typeof sceneRef.version.payload}.`,
12676
+ errors: []
12150
12677
  }
12151
12678
  };
12152
12679
  }
12153
- const camera = cameras[cameraIndex];
12154
- const presetRef = await refOf(
12680
+ scene = {
12681
+ element_id: sceneRef.version.element_id,
12682
+ version_id: sceneRef.version.version_id,
12683
+ payload: sceneRef.version.payload
12684
+ };
12685
+ return komponiere({
12686
+ shot: { element_id: shotElementId, version_id: shotVersionId, payload: shot },
12687
+ setup,
12688
+ scene,
12689
+ report,
12690
+ capabilities,
12691
+ canPlace,
12155
12692
  resolver,
12156
- camera.preset_ref,
12157
- "camera_preset",
12158
- `/camera_rig/cameras/${cameraIndex}/preset_ref`
12159
- );
12160
- if (!presetRef.ok) return { kind: "rejected", failure: presetRef.failure };
12161
- let pattern = null;
12162
- const placementSpec = isObject10(camera.placement) ? camera.placement : null;
12163
- if (placementSpec && isObject10(placementSpec.pattern_ref)) {
12164
- const patternRef = await refOf(
12165
- resolver,
12166
- placementSpec.pattern_ref,
12167
- "camera_pattern",
12168
- `/camera_rig/cameras/${cameraIndex}/placement/pattern_ref`
12169
- );
12170
- if (!patternRef.ok) return { kind: "rejected", failure: patternRef.failure };
12171
- pattern = patternRef.version.payload;
12693
+ contextChain,
12694
+ userInstruction,
12695
+ assumptions,
12696
+ diagnostics
12697
+ });
12698
+ }
12699
+ async function resolveScenePayload(input) {
12700
+ const {
12701
+ scenePayload,
12702
+ sceneElementId,
12703
+ sceneVersionId = "",
12704
+ resolver,
12705
+ contextChain,
12706
+ userInstruction
12707
+ } = input;
12708
+ if (!isObject11(scenePayload)) {
12709
+ return {
12710
+ kind: "rejected",
12711
+ failure: {
12712
+ class: "schema",
12713
+ where: "scene",
12714
+ message: `Die Szenen-Payload ist kein Objekt, sondern ${Array.isArray(scenePayload) ? "ein Array" : typeof scenePayload}.`,
12715
+ errors: []
12716
+ }
12717
+ };
12172
12718
  }
12173
- let shotConcept = null;
12174
- if (isObject10(shot.shot_concept_ref)) {
12175
- const conceptRef = await refOf(
12176
- resolver,
12177
- shot.shot_concept_ref,
12178
- "shot_concept",
12179
- "/shot_concept_ref"
12180
- );
12181
- if (!conceptRef.ok) return { kind: "rejected", failure: conceptRef.failure };
12182
- shotConcept = conceptRef.version.payload;
12719
+ const assumptions = [
12720
+ "Kein Scene Setup, kein Shot: Der Lauf entsteht aus der Szene allein. Bildaufbau, Kamera und Zielmodell wurden nicht ergaenzt, sondern sind nicht vorhanden (D-135)."
12721
+ ];
12722
+ const diagnostics = [];
12723
+ for (const fehler4 of validatePayload("scene", scenePayload).errors) {
12724
+ diagnostics.push(diagnosticOfSchemaError(fehler4, `Szene ${sceneElementId}`));
12725
+ }
12726
+ const faehig = sceneOnlyCapabilities(scenePayload);
12727
+ return komponiere({
12728
+ shot: null,
12729
+ setup: null,
12730
+ scene: { element_id: sceneElementId, version_id: sceneVersionId, payload: scenePayload },
12731
+ report: null,
12732
+ capabilities: {
12733
+ can_describe_scene: faehig.can_describe_scene.state,
12734
+ can_render_prompt: faehig.can_render_prompt.state,
12735
+ can_place: faehig.can_place.state
12736
+ },
12737
+ canPlace: false,
12738
+ resolver,
12739
+ contextChain,
12740
+ userInstruction,
12741
+ assumptions,
12742
+ diagnostics
12743
+ });
12744
+ }
12745
+ async function komponiere(z) {
12746
+ const {
12747
+ shot,
12748
+ setup,
12749
+ scene,
12750
+ report,
12751
+ capabilities,
12752
+ canPlace,
12753
+ resolver,
12754
+ contextChain,
12755
+ userInstruction,
12756
+ assumptions,
12757
+ diagnostics
12758
+ } = z;
12759
+ const inhalt = describableContent(scene.payload);
12760
+ if (!inhalt.ok) {
12761
+ return {
12762
+ kind: "rejected",
12763
+ failure: {
12764
+ class: "no_content",
12765
+ message: `Szene ${scene.element_id}: ${inhalt.message}`
12766
+ }
12767
+ };
12183
12768
  }
12184
- const styles = [];
12185
- for (const [ebene, refs] of [
12186
- ["scene_setup", asArray2(setup.style_refs)],
12187
- ["shot", asArray2(shot.style_refs)]
12188
- ]) {
12189
- for (const [i, ref] of refs.entries()) {
12190
- const resolved = await refOf(resolver, ref, "style", `/${ebene}/style_refs/${i}`);
12191
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
12769
+ const eingefroreneFaehigkeiten = {
12770
+ ...capabilities,
12771
+ can_render_prompt: "yes"
12772
+ };
12773
+ const shotOverrides = shot && isObject11(shot.payload.overrides) ? shot.payload.overrides : {};
12774
+ const settings = shot && isObject11(shot.payload.prompt_render_settings) ? shot.payload.prompt_render_settings : {};
12775
+ let camera = null;
12776
+ if (shot && setup) {
12777
+ const cameraId = str(shot.payload.camera_id);
12778
+ const rig = isObject11(setup.payload.camera_rig) ? setup.payload.camera_rig : {};
12779
+ const cameras = asArray3(rig.cameras);
12780
+ const cameraIndex = cameraId === null ? -1 : cameras.findIndex((c) => isObject11(c) && c.camera_id === cameraId);
12781
+ if (cameraId === null) {
12782
+ ausgelassen(
12783
+ diagnostics,
12784
+ "P-01",
12785
+ "/camera_id",
12786
+ `Der Shot ${shot.element_id} nennt keine camera_id. Der Prompt entsteht ohne Kameravorgabe; eine Kamera wird nicht erfunden (D-75).`
12787
+ );
12788
+ } else if (cameraIndex < 0) {
12789
+ ausgelassen(
12790
+ diagnostics,
12791
+ "P-01",
12792
+ "/camera_id",
12793
+ `Die aktive camera_id "${cameraId}" kommt im Rig der Scene-Setup-Version ${setup.version_id} nicht vor. Der Prompt entsteht ohne Kameravorgabe.`
12794
+ );
12795
+ } else {
12796
+ const rohKamera = cameras[cameraIndex];
12797
+ let preset = null;
12798
+ const presetRef = await refOf(
12799
+ resolver,
12800
+ rohKamera.preset_ref,
12801
+ "camera_preset",
12802
+ `/camera_rig/cameras/${cameraIndex}/preset_ref`
12803
+ );
12804
+ if (presetRef.ok) preset = presetRef.version.payload;
12805
+ else {
12806
+ ausgelassen(
12807
+ diagnostics,
12808
+ "P-04",
12809
+ `/camera_rig/cameras/${cameraIndex}/preset_ref`,
12810
+ `${presetRef.failure.message} Die Kamera geht ohne Preset in den Prompt.`
12811
+ );
12812
+ }
12813
+ let pattern = null;
12814
+ const placementSpec = isObject11(rohKamera.placement) ? rohKamera.placement : null;
12815
+ if (placementSpec && isObject11(placementSpec.pattern_ref)) {
12816
+ const patternRef = await refOf(
12817
+ resolver,
12818
+ placementSpec.pattern_ref,
12819
+ "camera_pattern",
12820
+ `/camera_rig/cameras/${cameraIndex}/placement/pattern_ref`
12821
+ );
12822
+ if (patternRef.ok) pattern = patternRef.version.payload;
12823
+ else {
12824
+ ausgelassen(
12825
+ diagnostics,
12826
+ "P-04",
12827
+ `/camera_rig/cameras/${cameraIndex}/placement/pattern_ref`,
12828
+ `${patternRef.failure.message} Das Kameramuster entfaellt im Prompt.`
12829
+ );
12830
+ }
12831
+ }
12832
+ const cameraPlacement = canPlace ? rohKamera.placement ?? null : entraeumlichtePlatzierung(rohKamera.placement, assumptions);
12833
+ camera = {
12834
+ camera_id: cameraId,
12835
+ name: str(rohKamera.name),
12836
+ preset,
12837
+ placement: cameraPlacement,
12838
+ orientation: rohKamera.orientation ?? null,
12839
+ // Der Shot darf Bildgroesse und Fokus ueberschreiben (D-40) — das ist
12840
+ // die oberste Stufe der Vorrangkette.
12841
+ framing: shotOverrides.framing ?? rohKamera.framing ?? null,
12842
+ focus: shotOverrides.focus !== void 0 ? shotOverrides.focus : rohKamera.focus ?? null,
12843
+ pattern
12844
+ };
12845
+ }
12846
+ } else if (shot && !setup) {
12847
+ ausgelassen(
12848
+ diagnostics,
12849
+ "P-01",
12850
+ "/camera_id",
12851
+ "Ohne Scene Setup gibt es kein Camera Rig. Der Prompt entsteht ohne Kameravorgabe."
12852
+ );
12853
+ }
12854
+ let shotConcept = null;
12855
+ if (shot && isObject11(shot.payload.shot_concept_ref)) {
12856
+ const conceptRef = await refOf(
12857
+ resolver,
12858
+ shot.payload.shot_concept_ref,
12859
+ "shot_concept",
12860
+ "/shot_concept_ref"
12861
+ );
12862
+ if (conceptRef.ok) shotConcept = conceptRef.version.payload;
12863
+ else {
12864
+ ausgelassen(
12865
+ diagnostics,
12866
+ "P-04",
12867
+ "/shot_concept_ref",
12868
+ `${conceptRef.failure.message} Das Shot Concept entfaellt im Prompt.`
12869
+ );
12870
+ }
12871
+ }
12872
+ const styles = [];
12873
+ for (const [ebene, refs] of [
12874
+ ["scene_setup", setup ? asArray3(setup.payload.style_refs) : []],
12875
+ ["shot", shot ? asArray3(shot.payload.style_refs) : []]
12876
+ ]) {
12877
+ for (const [i, ref] of refs.entries()) {
12878
+ const resolved = await refOf(resolver, ref, "style", `/${ebene}/style_refs/${i}`);
12879
+ if (!resolved.ok) {
12880
+ ausgelassen(
12881
+ diagnostics,
12882
+ "P-04",
12883
+ `/${ebene}/style_refs/${i}`,
12884
+ `${resolved.failure.message} Dieser Stil entfaellt im Prompt.`
12885
+ );
12886
+ continue;
12887
+ }
12192
12888
  const payload = resolved.version.payload;
12193
12889
  styles.push({
12194
- role: str(isObject10(ref) ? ref.role : null) ?? str(payload.role) ?? "unspecified",
12195
- rank: num(isObject10(ref) ? ref.rank : null) ?? 0,
12196
- weight: num(isObject10(ref) ? ref.weight : null),
12890
+ role: str(isObject11(ref) ? ref.role : null) ?? str(payload.role) ?? "unspecified",
12891
+ rank: num(isObject11(ref) ? ref.rank : null) ?? 0,
12892
+ weight: num(isObject11(ref) ? ref.weight : null),
12197
12893
  text: str(payload.text) ?? "",
12198
12894
  locale: str(payload.locale)
12199
12895
  });
12200
12896
  }
12201
12897
  }
12202
12898
  styles.sort((a, b) => a.rank - b.rank);
12203
- const settings = isObject10(shot.prompt_render_settings) ? shot.prompt_render_settings : {};
12204
12899
  const policies = [];
12205
- for (const [i, ref] of asArray2(settings.policy_refs).entries()) {
12206
- const resolved = await refOf(resolver, ref, "prompt_policy", `/prompt_render_settings/policy_refs/${i}`);
12207
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
12900
+ for (const [i, ref] of asArray3(settings.policy_refs).entries()) {
12901
+ const resolved = await refOf(
12902
+ resolver,
12903
+ ref,
12904
+ "prompt_policy",
12905
+ `/prompt_render_settings/policy_refs/${i}`
12906
+ );
12907
+ if (!resolved.ok) {
12908
+ ausgelassen(
12909
+ diagnostics,
12910
+ "P-04",
12911
+ `/prompt_render_settings/policy_refs/${i}`,
12912
+ `${resolved.failure.message} Diese Policy entfaellt im Prompt.`
12913
+ );
12914
+ continue;
12915
+ }
12208
12916
  const payload = resolved.version.payload;
12209
12917
  policies.push({
12210
12918
  subtype: str(payload.subtype) ?? "general",
@@ -12215,14 +12923,22 @@ async function resolveShotPayload(input) {
12215
12923
  }
12216
12924
  policies.sort((a, b) => a.rank - b.rank);
12217
12925
  const fragments = [];
12218
- for (const [i, ref] of asArray2(settings.fragment_refs).entries()) {
12926
+ for (const [i, ref] of asArray3(settings.fragment_refs).entries()) {
12219
12927
  const resolved = await refOf(
12220
12928
  resolver,
12221
12929
  ref,
12222
12930
  "prompt_fragment",
12223
12931
  `/prompt_render_settings/fragment_refs/${i}`
12224
12932
  );
12225
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
12933
+ if (!resolved.ok) {
12934
+ ausgelassen(
12935
+ diagnostics,
12936
+ "P-04",
12937
+ `/prompt_render_settings/fragment_refs/${i}`,
12938
+ `${resolved.failure.message} Dieses Fragment entfaellt im Prompt.`
12939
+ );
12940
+ continue;
12941
+ }
12226
12942
  const payload = resolved.version.payload;
12227
12943
  fragments.push({
12228
12944
  channel: str(payload.channel) ?? "positive",
@@ -12232,83 +12948,102 @@ async function resolveShotPayload(input) {
12232
12948
  });
12233
12949
  }
12234
12950
  fragments.sort((a, b) => a.rank - b.rank);
12235
- const key = str(settings.target_model_id);
12236
- if (!key) {
12237
- return {
12238
- kind: "rejected",
12239
- failure: {
12240
- class: "target_model_unresolvable",
12241
- message: "Der Shot nennt kein target_model_id.",
12242
- resolution: { kind: "not_found", key: "", chain: contextChain }
12243
- }
12244
- };
12245
- }
12246
- if (!resolver.resolveTargetModel) {
12951
+ let targetModelPayload = null;
12952
+ let targetModelResolution = null;
12953
+ const key = shot ? str(settings.target_model_id) : null;
12954
+ if (key === null) {
12955
+ ausgelassen(
12956
+ diagnostics,
12957
+ "P-17",
12958
+ "/prompt_render_settings/target_model_id",
12959
+ shot ? `Der Shot ${shot.element_id} nennt kein target_model_id. Der Prompt wird generisch abgeleitet, ohne Modelloptimierung.` : "Ohne Shot gibt es kein target_model_id. Der Prompt wird generisch abgeleitet, ohne Modelloptimierung."
12960
+ );
12961
+ } else if (!resolver.resolveTargetModel) {
12247
12962
  throw new ResolveTechnicalError(
12248
12963
  `Der Resolver bietet keine Zielmodellsuche an (kein ContextChainPort). Ein Lauf ohne Kontextkette wuerde ein Zielmodell melden, das nicht das gesuchte ist.`
12249
12964
  );
12250
- }
12251
- const targetModel = await resolver.resolveTargetModel(key, shotVersion.element_id);
12252
- if (targetModel.kind !== "resolved") {
12253
- return {
12254
- kind: "rejected",
12255
- failure: {
12256
- class: "target_model_unresolvable",
12257
- message: describeTargetModelFailure(targetModel),
12258
- resolution: targetModel
12965
+ } else {
12966
+ const targetModel = await resolver.resolveTargetModel(key, shot.element_id);
12967
+ if (targetModel.kind !== "resolved") {
12968
+ ausgelassen(
12969
+ diagnostics,
12970
+ "P-17",
12971
+ "/prompt_render_settings/target_model_id",
12972
+ `${describeTargetModelFailure(targetModel)} Der Prompt wird generisch abgeleitet, ohne Modelloptimierung.`
12973
+ );
12974
+ } else {
12975
+ targetModelPayload = targetModel.payload;
12976
+ targetModelResolution = {
12977
+ element_id: targetModel.elementId,
12978
+ version_id: targetModel.versionId,
12979
+ chain_index: targetModel.chainIndex,
12980
+ head: targetModel.head,
12981
+ shadowed_retired: targetModel.shadowedRetired.map((entry) => ({
12982
+ element_id: entry.elementId,
12983
+ context_id: entry.contextId
12984
+ }))
12985
+ };
12986
+ for (const uebergangen of targetModel.shadowedRetired) {
12987
+ assumptions.push(
12988
+ `Ein stillgelegtes target_model (${uebergangen.elementId}, Kontext ${uebergangen.contextId ?? "global"}) wurde uebergangen; verwendet wird ${targetModel.elementId} von Kettenglied ${targetModel.chainIndex}.`
12989
+ );
12259
12990
  }
12260
- };
12261
- }
12262
- for (const uebergangen of targetModel.shadowedRetired) {
12263
- assumptions.push(
12264
- `Ein stillgelegtes target_model (${uebergangen.elementId}, Kontext ${uebergangen.contextId ?? "global"}) wurde uebergangen; verwendet wird ${targetModel.elementId} von Kettenglied ${targetModel.chainIndex}.`
12265
- );
12266
- }
12267
- if (targetModel.head.kind === "selected" && targetModel.head.stale) {
12268
- assumptions.push(
12269
- `Die Auswahl des Zielmodell-Heads (${targetModel.versionId}) ist veraltet \u2014 es gibt neuere Heads. Die Auswahl gilt, weil sie getroffen wurde (D-36).`
12270
- );
12991
+ if (targetModel.head.kind === "selected" && targetModel.head.stale) {
12992
+ assumptions.push(
12993
+ `Die Auswahl des Zielmodell-Heads (${targetModel.versionId}) ist veraltet \u2014 es gibt neuere Heads. Die Auswahl gilt, weil sie getroffen wurde (D-36).`
12994
+ );
12995
+ }
12996
+ }
12271
12997
  }
12272
12998
  const overrides = /* @__PURE__ */ new Map();
12273
- for (const entry of asArray2(setup.node_overrides)) {
12274
- if (isObject10(entry) && typeof entry.node_id === "string") overrides.set(entry.node_id, entry);
12999
+ for (const entry of setup ? asArray3(setup.payload.node_overrides) : []) {
13000
+ if (isObject11(entry) && typeof entry.node_id === "string") overrides.set(entry.node_id, entry);
12275
13001
  }
12276
13002
  const placements = /* @__PURE__ */ new Map();
12277
- for (const entry of asArray2(setup.placements)) {
12278
- if (!isObject10(entry) || typeof entry.node_id !== "string") continue;
13003
+ for (const entry of setup ? asArray3(setup.payload.placements) : []) {
13004
+ if (!isObject11(entry) || typeof entry.node_id !== "string") continue;
12279
13005
  placements.set(entry.node_id, {
12280
- position: asArray2(entry.position),
12281
- ...entry.rotation_euler_deg ? { rotation_euler_deg: asArray2(entry.rotation_euler_deg) } : {},
12282
- ...entry.scale ? { scale: asArray2(entry.scale) } : {}
13006
+ position: asArray3(entry.position),
13007
+ ...entry.rotation_euler_deg ? { rotation_euler_deg: asArray3(entry.rotation_euler_deg) } : {},
13008
+ ...entry.scale ? { scale: asArray3(entry.scale) } : {}
12283
13009
  });
12284
13010
  }
12285
- const shotOverrides = isObject10(shot.overrides) ? shot.overrides : {};
12286
- const hidden = new Set(asArray2(shotOverrides.hidden_nodes).filter((v) => typeof v === "string"));
13011
+ const hidden = new Set(
13012
+ asArray3(shotOverrides.hidden_nodes).filter((v) => typeof v === "string")
13013
+ );
12287
13014
  const nodes = [];
12288
- for (const raw of asArray2(scene.nodes)) {
12289
- if (!isObject10(raw) || typeof raw.node_id !== "string") continue;
13015
+ for (const raw of asArray3(scene.payload.nodes)) {
13016
+ if (!isObject11(raw) || typeof raw.node_id !== "string") continue;
12290
13017
  const nodeId = raw.node_id;
12291
13018
  const contributions = [];
12292
- for (const [i, ref] of asArray2(raw.component_refs).entries()) {
13019
+ for (const [i, ref] of asArray3(raw.component_refs).entries()) {
12293
13020
  const resolved = await refOf(
12294
13021
  resolver,
12295
13022
  ref,
12296
13023
  "scene_component",
12297
13024
  `/nodes/${nodeId}/component_refs/${i}`
12298
13025
  );
12299
- if (!resolved.ok) return { kind: "rejected", failure: resolved.failure };
13026
+ if (!resolved.ok) {
13027
+ ausgelassen(
13028
+ diagnostics,
13029
+ "P-05",
13030
+ `/nodes/${nodeId}/component_refs/${i}`,
13031
+ `${resolved.failure.message} Dieser Beitrag entfaellt; der Knoten bleibt mit seinen uebrigen Beitraegen im Prompt.`
13032
+ );
13033
+ continue;
13034
+ }
12300
13035
  const payload = resolved.version.payload;
12301
13036
  contributions.push({
12302
13037
  source: "component",
12303
13038
  element_id: resolved.version.element_id,
12304
13039
  version_id: resolved.version.version_id,
12305
- role: str(isObject10(ref) ? ref.role : null),
12306
- rank: num(isObject10(ref) ? ref.rank : null) ?? 0,
13040
+ role: str(isObject11(ref) ? ref.role : null),
13041
+ rank: num(isObject11(ref) ? ref.rank : null) ?? 0,
12307
13042
  locale: str(payload.locale),
12308
13043
  text: str(payload.text) ?? ""
12309
13044
  });
12310
13045
  }
12311
- const semantic = isObject10(raw.semantic) ? raw.semantic : null;
13046
+ const semantic = isObject11(raw.semantic) ? raw.semantic : null;
12312
13047
  if (semantic && str(semantic.description)) {
12313
13048
  contributions.push({
12314
13049
  source: "node_semantic",
@@ -12322,12 +13057,12 @@ async function resolveShotPayload(input) {
12322
13057
  });
12323
13058
  }
12324
13059
  const override = overrides.get(nodeId);
12325
- const overrideSemantic = override && isObject10(override.semantic) ? override.semantic : null;
12326
- if (overrideSemantic && str(overrideSemantic.description)) {
13060
+ const overrideSemantic = override && isObject11(override.semantic) ? override.semantic : null;
13061
+ if (overrideSemantic && str(overrideSemantic.description) && setup) {
12327
13062
  contributions.push({
12328
13063
  source: "setup_override",
12329
- element_id: setupRef.version.element_id,
12330
- version_id: setupRef.version.version_id,
13064
+ element_id: setup.element_id,
13065
+ version_id: setup.version_id,
12331
13066
  role: null,
12332
13067
  rank: Number.MAX_SAFE_INTEGER,
12333
13068
  locale: null,
@@ -12336,8 +13071,8 @@ async function resolveShotPayload(input) {
12336
13071
  }
12337
13072
  contributions.sort((a, b) => a.rank - b.rank);
12338
13073
  const properties = {
12339
- ...isObject10(semantic?.properties) ? semantic.properties : {},
12340
- ...isObject10(overrideSemantic?.properties) ? overrideSemantic.properties : {}
13074
+ ...isObject11(semantic?.properties) ? semantic.properties : {},
13075
+ ...isObject11(overrideSemantic?.properties) ? overrideSemantic.properties : {}
12341
13076
  };
12342
13077
  nodes.push({
12343
13078
  node_id: nodeId,
@@ -12348,9 +13083,6 @@ async function resolveShotPayload(input) {
12348
13083
  hidden: hidden.has(nodeId)
12349
13084
  });
12350
13085
  }
12351
- const cameraPlacement = canPlace ? camera.placement ?? null : entraeumlichtePlatzierung(camera.placement, assumptions);
12352
- const framing = shotOverrides.framing ?? camera.framing;
12353
- const focus = shotOverrides.focus !== void 0 ? shotOverrides.focus : camera.focus ?? null;
12354
13086
  const shotInstruction = str(settings.user_instruction);
12355
13087
  if (userInstruction && shotInstruction && userInstruction !== shotInstruction) {
12356
13088
  assumptions.push(
@@ -12364,56 +13096,37 @@ async function resolveShotPayload(input) {
12364
13096
  kind: "resolved",
12365
13097
  report,
12366
13098
  input: {
12367
- shot: {
12368
- version_id: shotVersion.version_id,
12369
- element_id: shotVersion.element_id,
12370
- camera_id: cameraId,
13099
+ shot: shot ? {
13100
+ version_id: shot.version_id,
13101
+ element_id: shot.element_id,
13102
+ camera_id: camera ? camera.camera_id : null,
12371
13103
  shot_concept: shotConcept,
12372
13104
  // Der Aufrufer darf die im Shot hinterlegte Anweisung ueberschreiben
12373
13105
  // (§4.1). Beide Herkuenfte sind unterschiedliche Sachverhalte, deshalb
12374
13106
  // wird der Fall in `assumptions` benannt statt still ersetzt.
12375
- user_instruction: userInstruction ?? str(settings.user_instruction),
13107
+ user_instruction: userInstruction ?? shotInstruction,
12376
13108
  text_override: str(shotOverrides.text)
12377
- },
13109
+ } : null,
13110
+ setup: setup ? { version_id: setup.version_id, element_id: setup.element_id } : null,
12378
13111
  scene: {
12379
- version_id: sceneRef.version.version_id,
13112
+ element_id: scene.element_id,
13113
+ version_id: scene.version_id,
12380
13114
  nodes,
12381
- relations: asArray2(scene.relations),
12382
- environment: scene.environment ?? null,
12383
- unit_system: scene.unit_system ?? null
12384
- },
12385
- camera: {
12386
- camera_id: cameraId,
12387
- name: str(camera.name),
12388
- preset: presetRef.version.payload,
12389
- placement: cameraPlacement,
12390
- orientation: camera.orientation ?? null,
12391
- framing: framing ?? null,
12392
- focus,
12393
- pattern
13115
+ relations: asArray3(scene.payload.relations),
13116
+ environment: scene.payload.environment ?? null,
13117
+ unit_system: scene.payload.unit_system ?? null
12394
13118
  },
13119
+ camera,
12395
13120
  styles,
12396
13121
  policies,
12397
13122
  fragments,
12398
- target_model: targetModel.payload,
13123
+ target_model: targetModelPayload,
12399
13124
  localization_notes: [],
12400
13125
  assumptions,
12401
- capabilities: {
12402
- can_describe_scene: report.can_describe_scene.state,
12403
- can_render_prompt: report.can_render_prompt.state,
12404
- can_place: report.can_place.state
12405
- },
13126
+ diagnostics,
13127
+ capabilities: eingefroreneFaehigkeiten,
12406
13128
  context_chain: [...contextChain],
12407
- target_model_resolution: {
12408
- element_id: targetModel.elementId,
12409
- version_id: targetModel.versionId,
12410
- chain_index: targetModel.chainIndex,
12411
- head: targetModel.head,
12412
- shadowed_retired: targetModel.shadowedRetired.map((entry) => ({
12413
- element_id: entry.elementId,
12414
- context_id: entry.contextId
12415
- }))
12416
- }
13129
+ target_model_resolution: targetModelResolution
12417
13130
  }
12418
13131
  };
12419
13132
  }
@@ -12585,9 +13298,117 @@ async function freezeDraftChain(input) {
12585
13298
  ...shot.chain.source_recovery_id ? { sourceRecoveryId: shot.chain.source_recovery_id } : {}
12586
13299
  };
12587
13300
  }
13301
+ function ladeSzene(sicht, elementId, contextChain) {
13302
+ const gelesen = sicht.getElement(elementId);
13303
+ if (gelesen.kind !== "ok") {
13304
+ return {
13305
+ fehler: gelesen.message ?? `Element ${elementId} konnte nicht gelesen werden.`,
13306
+ technisch: true
13307
+ };
13308
+ }
13309
+ const snapshot = gelesen.value;
13310
+ if (!snapshot) return { fehler: `Element ${elementId} ist unbekannt.` };
13311
+ if (snapshot.element.type !== "scene") {
13312
+ return {
13313
+ fehler: `Element ${elementId} ist vom Typ "${snapshot.element.type}", erwartet "scene".`
13314
+ };
13315
+ }
13316
+ if (snapshot.draftFork) {
13317
+ return {
13318
+ fehler: `Element ${elementId} hat parallele Entwuerfe. Solange sie nicht aufgeloest sind, gibt es keinen eindeutigen Arbeitsstand (D-29).`
13319
+ };
13320
+ }
13321
+ if (snapshot.draft) {
13322
+ return {
13323
+ element_id: elementId,
13324
+ draft_id: snapshot.draft.draft_id,
13325
+ revision: snapshot.draft.revision,
13326
+ version_id: null,
13327
+ payload: snapshot.draft.payload
13328
+ };
13329
+ }
13330
+ const versionen = snapshot.versions ?? [];
13331
+ if (versionen.length === 0) {
13332
+ return {
13333
+ fehler: `Element ${elementId} hat weder einen Entwurf noch eine veroeffentlichte Version. Es gibt nichts einzufrieren.`
13334
+ };
13335
+ }
13336
+ const kopf = effectivePreferredHeadSafe(
13337
+ { element: snapshot.element, versions: versionen, preferredHeads: snapshot.preferredHeads },
13338
+ contextChain
13339
+ );
13340
+ if (kopf.kind === "dag_fehler") {
13341
+ return { fehler: `Der Versionsgraph von Element ${elementId} ist nicht aufbaubar: ${kopf.message}` };
13342
+ }
13343
+ const versionId = usableHeadVersionId(resolutionOf(kopf));
13344
+ if (!versionId) {
13345
+ return {
13346
+ fehler: `Element ${elementId} hat mehrere veroeffentlichte Koepfe und in diesem Kontext keine Auswahl. Welcher Stand gilt, entscheidet keine Reihenfolge (D-36) \u2014 bitte einen bevorzugten Kopf setzen.`
13347
+ };
13348
+ }
13349
+ const version = versionen.find((v) => v.version_id === versionId);
13350
+ if (!version) {
13351
+ return {
13352
+ fehler: `Die wirksame Version ${versionId} von Element ${elementId} steht nicht in der gelesenen Momentaufnahme.`
13353
+ };
13354
+ }
13355
+ return {
13356
+ element_id: elementId,
13357
+ draft_id: null,
13358
+ revision: null,
13359
+ version_id: versionId,
13360
+ payload: version.payload
13361
+ };
13362
+ }
13363
+ async function freezeSceneWorkingState(input) {
13364
+ const { sceneElementId, store, resolver, contextChain, userInstruction } = input;
13365
+ const a = await store.readSnapshot({ fresh: false });
13366
+ const szene = ladeSzene(a, sceneElementId, contextChain);
13367
+ if ("fehler" in szene) return ausfallErgebnis(szene);
13368
+ const b = await store.readSnapshot({ fresh: true });
13369
+ const erneut = ladeSzene(b, sceneElementId, contextChain);
13370
+ if ("fehler" in erneut) return ausfallErgebnis(erneut);
13371
+ if (erneut.draft_id !== szene.draft_id || erneut.revision !== szene.revision || erneut.version_id !== szene.version_id) {
13372
+ return {
13373
+ kind: "conflict",
13374
+ message: `Der Arbeitsstand der Szene ${sceneElementId} hat sich waehrend des Einfrierens geaendert (erwartet ${szene.draft_id ? `Entwurf ${szene.draft_id}, Revision ${szene.revision}` : `Version ${szene.version_id}`}, vorhanden ${erneut.draft_id ? `Entwurf ${erneut.draft_id}, Revision ${erneut.revision}` : `Version ${erneut.version_id}`}). Es wurde kein Modell gerufen.`,
13375
+ node: { type: "scene", element_id: sceneElementId, draft_id: szene.draft_id ?? "" },
13376
+ expectedRevision: szene.revision ?? 0,
13377
+ actualRevision: erneut.revision ?? 0
13378
+ };
13379
+ }
13380
+ const aufgeloest = await resolveScenePayload({
13381
+ scenePayload: szene.payload,
13382
+ sceneElementId: szene.element_id,
13383
+ // Ein Entwurf hat keine Version — und bekommt hier auch keine erfundene
13384
+ // (D-98/D-75).
13385
+ sceneVersionId: szene.version_id ?? "",
13386
+ resolver,
13387
+ contextChain,
13388
+ userInstruction
13389
+ });
13390
+ if (aufgeloest.kind !== "resolved") {
13391
+ return {
13392
+ kind: "rejected",
13393
+ message: aufgeloest.failure.message,
13394
+ failure: aufgeloest.failure
13395
+ };
13396
+ }
13397
+ return {
13398
+ kind: "ok",
13399
+ scene: {
13400
+ element_id: szene.element_id,
13401
+ draft_id: szene.draft_id,
13402
+ revision: szene.revision,
13403
+ version_id: szene.version_id
13404
+ },
13405
+ input: aufgeloest.input
13406
+ };
13407
+ }
12588
13408
 
12589
13409
  // src/lib/szenen/promptRun.ts
12590
13410
  function buildSystemInstruction2(input) {
13411
+ const ohneZielmodell = input.target_model === null || input.target_model === void 0;
12591
13412
  const model = input.target_model ?? {};
12592
13413
  const sprache = typeof model.prompt_language === "string" ? model.prompt_language : "en";
12593
13414
  const negativ = model.supports_negative_prompt === true;
@@ -12608,7 +13429,11 @@ function buildSystemInstruction2(input) {
12608
13429
  "",
12609
13430
  `Der Prompt wird in der Sprache "${sprache}" formuliert.`
12610
13431
  ];
12611
- if (!negativ) {
13432
+ if (ohneZielmodell) {
13433
+ zeilen.push(
13434
+ 'Es ist KEIN Zielmodell angegeben. Formuliere einen generischen Prompt und richte ihn nicht an einer bestimmten Bildmodell-Syntax aus. "negative" bleibt null, weil kein Modell zugesagt hat, ein Negativfeld zu fuehren; was mit negativen Fragmenten geschehen ist, gehoert in "notes".'
13435
+ );
13436
+ } else if (!negativ) {
12612
13437
  zeilen.push(
12613
13438
  'Das Zielmodell kennt KEIN Negativ-Prompt-Feld. "negative" bleibt null; was mit negativen Fragmenten geschehen ist, gehoert in "notes".'
12614
13439
  );
@@ -12637,6 +13462,14 @@ function buildSystemInstruction2(input) {
12637
13462
  'Widersprechen sie einander, nenne den Widerspruch mit beiden Quellen in "notes" \u2014',
12638
13463
  "waehle nicht still eine Seite."
12639
13464
  );
13465
+ if (input.camera === null) {
13466
+ zeilen.push(
13467
+ "",
13468
+ "Es ist KEINE Kamera angegeben. Erfinde keine Brennweite, keinen Bildausschnitt",
13469
+ "und keine Kameraposition. Wo eine Kameraaussage noetig waere, formuliere sie",
13470
+ 'als Annahme und nenne sie in "notes".'
13471
+ );
13472
+ }
12640
13473
  if (input.capabilities.can_place !== "yes") {
12641
13474
  zeilen.push(
12642
13475
  "",
@@ -12650,7 +13483,7 @@ function buildSystemInstruction2(input) {
12650
13483
  function buildUserPrompt2(input) {
12651
13484
  return JSON.stringify(input, null, 2);
12652
13485
  }
12653
- var isObject11 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
13486
+ var isObject12 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
12654
13487
  function parseRunResponse(raw) {
12655
13488
  const text = raw.trim().replace(/^```(?:json)?\s*/i, "").replace(/\s*```$/, "").trim();
12656
13489
  if (text.length === 0) return { ok: false, message: "Die Antwort war leer." };
@@ -12664,7 +13497,7 @@ function parseRunResponse(raw) {
12664
13497
  }
12665
13498
  }
12666
13499
  function checkRunResponse(value, input) {
12667
- if (!isObject11(value)) {
13500
+ if (!isObject12(value)) {
12668
13501
  return { ok: false, message: `Die Antwort ist kein Objekt, sondern ${Array.isArray(value) ? "array" : typeof value}.` };
12669
13502
  }
12670
13503
  if (typeof value.positive !== "string" || value.positive.trim().length === 0) {
@@ -12682,11 +13515,11 @@ function checkRunResponse(value, input) {
12682
13515
  if (negative !== null && !negativErlaubt) {
12683
13516
  return {
12684
13517
  ok: false,
12685
- message: `Das Zielmodell fuehrt kein Negativ-Prompt-Feld (supports_negative_prompt = false), die Antwort liefert aber eines.`
13518
+ message: input.target_model ? `Das Zielmodell fuehrt kein Negativ-Prompt-Feld (supports_negative_prompt = false), die Antwort liefert aber eines.` : `Dieser Lauf hat kein Zielmodell (generische Ableitung); ein Negativ-Prompt-Feld ist damit nicht zugesagt, die Antwort liefert aber eines.`
12686
13519
  };
12687
13520
  }
12688
13521
  const visibility = value.visibility;
12689
- if (!isObject11(visibility)) {
13522
+ if (!isObject12(visibility)) {
12690
13523
  return { ok: false, message: '"visibility" fehlt \u2014 die Pflichtdiagnosen aus D-21.' };
12691
13524
  }
12692
13525
  if (typeof visibility.basis !== "string") {
@@ -12698,7 +13531,7 @@ function checkRunResponse(value, input) {
12698
13531
  const genannt = /* @__PURE__ */ new Set();
12699
13532
  const nodes = [];
12700
13533
  for (const eintrag of visibility.nodes) {
12701
- if (!isObject11(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
13534
+ if (!isObject12(eintrag) || typeof eintrag.node_id !== "string" || typeof eintrag.state !== "string") {
12702
13535
  return { ok: false, message: 'Ein Eintrag in "visibility.nodes" hat keine node_id oder keinen state.' };
12703
13536
  }
12704
13537
  genannt.add(eintrag.node_id);
@@ -12843,6 +13676,23 @@ function createEventLogRunPersistence(channel) {
12843
13676
  return queryError(error, `Laeufe der Kette ${chainId} konnten nicht gelesen werden`);
12844
13677
  }
12845
13678
  },
13679
+ async listForScene(sceneElementId) {
13680
+ try {
13681
+ const events = await channel.readEvents();
13682
+ return {
13683
+ kind: "ok",
13684
+ value: collectPromptRuns(events).filter((run) => {
13685
+ const quelle = sourceOf(run);
13686
+ return quelle.kind === "scene_direct" && quelle.scene.element_id === sceneElementId;
13687
+ })
13688
+ };
13689
+ } catch (error) {
13690
+ return queryError(
13691
+ error,
13692
+ `Laeufe der Szene ${sceneElementId} konnten nicht gelesen werden`
13693
+ );
13694
+ }
13695
+ },
12846
13696
  async record(record) {
12847
13697
  try {
12848
13698
  await channel.appendEvent(SZENEN_EVENT_TYPES.promptRunRecorded, record);
@@ -12929,13 +13779,21 @@ function createClientRunPort(options) {
12929
13779
  return { kind: "error", message: resolved.failure.message, retryable: false };
12930
13780
  }
12931
13781
  const outcome = await runPromptDerivation(resolved.input, text);
13782
+ if (!resolved.input.shot) {
13783
+ return {
13784
+ kind: "error",
13785
+ message: `Die Aufloesung der Shot-Version ${input.shotVersionId} lieferte eine Eingabe ohne Shot. Das ist ein Programmfehler, kein Lauf.`,
13786
+ retryable: false
13787
+ };
13788
+ }
12932
13789
  const record = {
12933
13790
  run_id: newRunId(),
12934
13791
  shot_version_id: input.shotVersionId,
12935
13792
  shot_element_id: resolved.input.shot.element_id,
12936
13793
  scene_setup_version_id: resolved.input.scene.version_id,
12937
- camera_id: resolved.input.shot.camera_id,
12938
- target_model_version_id: resolved.input.target_model_resolution.version_id,
13794
+ // Leer heisst „kein Wert", nicht „Wert unbekannt" (D-75/D-135).
13795
+ camera_id: resolved.input.shot.camera_id ?? "",
13796
+ target_model_version_id: resolved.input.target_model_resolution?.version_id ?? "",
12939
13797
  provider: outcome.provider,
12940
13798
  model_id: outcome.model_id,
12941
13799
  system_prompt: outcome.system_prompt,
@@ -13007,8 +13865,8 @@ function createClientRunPort(options) {
13007
13865
  shot_version_id: "",
13008
13866
  shot_element_id: input.shotElementId,
13009
13867
  scene_setup_version_id: "",
13010
- camera_id: eingefroren.input.shot.camera_id,
13011
- target_model_version_id: eingefroren.input.target_model_resolution.version_id,
13868
+ camera_id: eingefroren.input.shot?.camera_id ?? "",
13869
+ target_model_version_id: eingefroren.input.target_model_resolution?.version_id ?? "",
13012
13870
  provider: outcome.provider,
13013
13871
  model_id: outcome.model_id,
13014
13872
  system_prompt: outcome.system_prompt,
@@ -13042,6 +13900,95 @@ function createClientRunPort(options) {
13042
13900
  async listRunsForChain(chainId) {
13043
13901
  const alle = await runs.listForChain(chainId);
13044
13902
  return alle;
13903
+ },
13904
+ // ── Der Lauf direkt aus einer Szene (D-135) ───────────────────────────
13905
+ //
13906
+ // Bewusst **derselbe** Ablauf wie oben: Kontext ermitteln, Kette
13907
+ // aufloesen, einfrieren, dann erst rufen. Was sich unterscheidet, ist
13908
+ // ausschliesslich, **was** eingefroren wird — ein Szenen-Arbeitsstand
13909
+ // statt einer Drei-Knoten-Kette.
13910
+ async startRunFromScene(input) {
13911
+ try {
13912
+ let contextId = input.contextId;
13913
+ if (contextId === void 0) {
13914
+ const element = await elements.getElement(input.sceneElementId);
13915
+ if (element.kind !== "ok") {
13916
+ return { kind: "error", message: element.message, retryable: element.retryable };
13917
+ }
13918
+ if (element.value === null) {
13919
+ return {
13920
+ kind: "error",
13921
+ message: `Element ${input.sceneElementId} ist unbekannt.`,
13922
+ retryable: false
13923
+ };
13924
+ }
13925
+ contextId = element.value.element.context_id;
13926
+ }
13927
+ const chain = await context.chainFor(contextId ?? null);
13928
+ if (chain.kind !== "ok") {
13929
+ return { kind: "error", message: chain.message, retryable: chain.retryable };
13930
+ }
13931
+ const eingefroren = await freezeSceneWorkingState({
13932
+ sceneElementId: input.sceneElementId,
13933
+ store: elements,
13934
+ resolver,
13935
+ contextChain: chain.value,
13936
+ userInstruction: input.userInstruction ?? null
13937
+ });
13938
+ if (eingefroren.kind === "conflict") {
13939
+ return {
13940
+ kind: "conflict",
13941
+ message: eingefroren.message,
13942
+ node: eingefroren.node,
13943
+ expectedRevision: eingefroren.expectedRevision,
13944
+ actualRevision: eingefroren.actualRevision
13945
+ };
13946
+ }
13947
+ if (eingefroren.kind === "error") {
13948
+ return { kind: "error", message: eingefroren.message, retryable: eingefroren.retryable };
13949
+ }
13950
+ if (eingefroren.kind !== "ok") {
13951
+ return { kind: "rejected", message: eingefroren.message };
13952
+ }
13953
+ const outcome = await runPromptDerivation(eingefroren.input, text);
13954
+ const record = {
13955
+ run_id: newRunId(),
13956
+ // Keine fingierten Kennungen (D-98/D-75). Was es nicht gibt, bleibt
13957
+ // leer — die Herkunft steht in `source`.
13958
+ shot_version_id: "",
13959
+ shot_element_id: "",
13960
+ scene_setup_version_id: "",
13961
+ camera_id: "",
13962
+ target_model_version_id: eingefroren.input.target_model_resolution?.version_id ?? "",
13963
+ provider: outcome.provider,
13964
+ model_id: outcome.model_id,
13965
+ system_prompt: outcome.system_prompt,
13966
+ input_payload: eingefroren.input,
13967
+ status: outcome.status,
13968
+ failure: outcome.status === "failed" ? outcome.failure : null,
13969
+ output: outcome.status === "succeeded" ? outcome.output : null,
13970
+ raw_output: outcome.raw_output,
13971
+ source: { kind: "scene_direct", scene: eingefroren.scene },
13972
+ created_at: now().toISOString()
13973
+ };
13974
+ return await runs.record(record);
13975
+ } catch (error) {
13976
+ return {
13977
+ kind: "error",
13978
+ message: `Prompt-Lauf aus der Szene ${input.sceneElementId} ist fehlgeschlagen: ${error instanceof Error ? error.message : String(error)}`,
13979
+ retryable: true
13980
+ };
13981
+ }
13982
+ },
13983
+ async listRunsForScene(sceneElementId) {
13984
+ try {
13985
+ return await runs.listForScene(sceneElementId);
13986
+ } catch (error) {
13987
+ return queryError(
13988
+ error,
13989
+ `Laeufe der Szene ${sceneElementId} konnten nicht gelesen werden`
13990
+ );
13991
+ }
13045
13992
  }
13046
13993
  };
13047
13994
  }
@@ -13141,6 +14088,7 @@ function createHfImageStore(options) {
13141
14088
  const basisMs = options.leseBasisMs ?? 400;
13142
14089
  const schlafen = options.schlafen ?? warten;
13143
14090
  const abgelegt = /* @__PURE__ */ new Map();
14091
+ const vorschauen = /* @__PURE__ */ new Map();
13144
14092
  const bekanntePfade = /* @__PURE__ */ new Set();
13145
14093
  let gefalteterBestand = null;
13146
14094
  let laufenderAbgleich = null;
@@ -13164,7 +14112,7 @@ function createHfImageStore(options) {
13164
14112
  }
13165
14113
  return laufenderAbgleich;
13166
14114
  }
13167
- return {
14115
+ const speicher = {
13168
14116
  bestand: bestandAbgleichen,
13169
14117
  async putWithId(id, base64, mimeType, titel) {
13170
14118
  const echterTyp = typAusBytes(base64, mimeType);
@@ -13183,6 +14131,38 @@ function createHfImageStore(options) {
13183
14131
  }, []);
13184
14132
  abgelegt.set(id, { data: base64, mimeType: echterTyp });
13185
14133
  },
14134
+ async preview(id) {
14135
+ const bekannt = vorschauen.get(id);
14136
+ if (bekannt) return bekannt;
14137
+ const eben = abgelegt.get(id);
14138
+ if (eben) {
14139
+ const quelle2 = `data:${eben.mimeType};base64,${eben.data}`;
14140
+ vorschauen.set(id, quelle2);
14141
+ return quelle2;
14142
+ }
14143
+ const zustand = await bestandAbgleichen();
14144
+ const eintrag = zustand.metadata.find((e) => e.id === id);
14145
+ if (eintrag?.hasThumb && eintrag.filename) {
14146
+ const klein = await hfLoadImageAsBase64(
14147
+ id,
14148
+ token,
14149
+ void 0,
14150
+ eintrag.filename,
14151
+ void 0,
14152
+ eintrag.mimeType,
14153
+ true
14154
+ );
14155
+ if (klein) {
14156
+ const quelle2 = `data:${eintrag.mimeType || "image/jpeg"};base64,${klein}`;
14157
+ vorschauen.set(id, quelle2);
14158
+ return quelle2;
14159
+ }
14160
+ }
14161
+ const voll = await speicher.resolve(id);
14162
+ const quelle = `data:${voll.mimeType};base64,${voll.data}`;
14163
+ vorschauen.set(id, quelle);
14164
+ return quelle;
14165
+ },
13186
14166
  async resolve(id, mimeType) {
13187
14167
  const eben = abgelegt.get(id);
13188
14168
  if (eben) return eben;
@@ -13220,6 +14200,47 @@ function createHfImageStore(options) {
13220
14200
  );
13221
14201
  }
13222
14202
  };
14203
+ return speicher;
14204
+ }
14205
+
14206
+ // src/lib/szenen/libraryItems.ts
14207
+ var LOCATOR = /^(.+)-(\d+)$/;
14208
+ function locatorTeile(mediaRef) {
14209
+ const treffer = LOCATOR.exec(mediaRef);
14210
+ if (!treffer) return { stamm: mediaRef, position: null };
14211
+ return { stamm: treffer[1], position: Number(treffer[2]) };
14212
+ }
14213
+ function gruppiereZuItems(bilder) {
14214
+ const gruppen = /* @__PURE__ */ new Map();
14215
+ for (const bild of bilder) {
14216
+ const { stamm } = locatorTeile(bild.mediaRef);
14217
+ const vorhanden = gruppen.get(stamm);
14218
+ if (vorhanden) vorhanden.push(bild);
14219
+ else gruppen.set(stamm, [bild]);
14220
+ }
14221
+ const items = [...gruppen.entries()].map(([stamm, mitglieder]) => {
14222
+ const sortiert = [...mitglieder].sort((a, b) => {
14223
+ const pa = locatorTeile(a.mediaRef).position ?? 0;
14224
+ const pb = locatorTeile(b.mediaRef).position ?? 0;
14225
+ return pa - pb;
14226
+ });
14227
+ const erstes = sortiert[0];
14228
+ const itemRef = sortiert.length === 1 ? erstes.mediaRef : stamm;
14229
+ const juengstes = sortiert.reduce(
14230
+ (max, b) => Math.max(max, b.timestamp ?? 0),
14231
+ 0
14232
+ );
14233
+ return {
14234
+ item: {
14235
+ itemRef,
14236
+ title: erstes.itemTitle?.trim() || erstes.title || itemRef,
14237
+ images: sortiert.map(({ timestamp: _t, itemTitle: _i, ...bild }) => bild)
14238
+ },
14239
+ juengstes
14240
+ };
14241
+ });
14242
+ items.sort((a, b) => b.juengstes - a.juengstes);
14243
+ return items.map((e) => e.item);
13223
14244
  }
13224
14245
 
13225
14246
  // src/lib/szenen/hfImageLibrary.ts
@@ -13227,13 +14248,22 @@ function fehler2(nachricht, retryable = false) {
13227
14248
  return { kind: "error", message: nachricht, retryable };
13228
14249
  }
13229
14250
  function alsBild(eintrag) {
14251
+ const { position } = locatorTeile(eintrag.id);
14252
+ const werk = eintrag.prompt?.trim() || "";
13230
14253
  return {
13231
14254
  mediaRef: eintrag.id,
13232
- // Der Prompt ist der einzige menschenlesbare Text, den ein Bild dort trägt.
13233
- // Fehlt er, ist die Kennung ehrlicher als ein erfundener Name.
13234
- title: eintrag.prompt?.trim() || eintrag.id,
14255
+ // Innerhalb eines mehrbildigen Werkes tragen alle Einträge denselben
14256
+ // Prompt — der Abgleich schreibt ihn je Bild aus derselben Library-Zeile.
14257
+ // Deshalb bekommt die Kachel dort die Position dazu, sonst stünde
14258
+ // vierzehnmal derselbe Satz.
14259
+ title: position === null ? werk || eintrag.id : `${werk || eintrag.id} \xB7 Bild ${position + 1}`,
13235
14260
  mimeType: eintrag.mimeType || "image/jpeg",
13236
- thumbUrl: null
14261
+ // Kein `thumbUrl`: Die Datei liegt auf HF hinter einem Token, und ein
14262
+ // `<img src>` käme dort nicht durch. Die Quelle entsteht über
14263
+ // `loadPreview()` — und nur für die Kacheln, die wirklich gezeigt werden.
14264
+ thumbUrl: null,
14265
+ itemTitle: werk || null,
14266
+ ...typeof eintrag.timestamp === "number" ? { timestamp: eintrag.timestamp } : {}
13237
14267
  };
13238
14268
  }
13239
14269
  function createHfImageLibrary(options) {
@@ -13244,15 +14274,14 @@ function createHfImageLibrary(options) {
13244
14274
  ...options.now ? { now: options.now } : {}
13245
14275
  });
13246
14276
  return {
13247
- async listImages(query) {
14277
+ async listItems(query) {
13248
14278
  try {
13249
14279
  const zustand = await store.bestand();
13250
14280
  const eintraege = zustand?.metadata ?? [];
14281
+ const items = gruppiereZuItems(eintraege.map(alsBild));
13251
14282
  const gesucht = query?.search?.trim().toLowerCase();
13252
- const gefiltert = gesucht ? eintraege.filter((e) => (e.prompt ?? "").toLowerCase().includes(gesucht) || e.id.toLowerCase().includes(gesucht)) : eintraege;
13253
- const sortiert = [...gefiltert].sort((a, b) => (b.timestamp ?? 0) - (a.timestamp ?? 0));
13254
- const begrenzt = query?.limit ? sortiert.slice(0, query.limit) : sortiert;
13255
- return { kind: "ok", value: begrenzt.map(alsBild) };
14283
+ const gefiltert = gesucht ? items.filter((i) => i.title.toLowerCase().includes(gesucht) || i.itemRef.toLowerCase().includes(gesucht)) : items;
14284
+ return { kind: "ok", value: query?.limit ? gefiltert.slice(0, query.limit) : gefiltert };
13256
14285
  } catch (error) {
13257
14286
  return fehler2(
13258
14287
  `Der Bildbestand konnte nicht gelesen werden: ${error instanceof Error ? error.message : String(error)}`,
@@ -13260,6 +14289,16 @@ function createHfImageLibrary(options) {
13260
14289
  );
13261
14290
  }
13262
14291
  },
14292
+ async loadPreview(mediaRef) {
14293
+ try {
14294
+ return { kind: "ok", value: await store.preview(mediaRef) };
14295
+ } catch (error) {
14296
+ return fehler2(
14297
+ `Die Vorschau von ${mediaRef} ist nicht ladbar: ${error instanceof Error ? error.message : String(error)}`,
14298
+ true
14299
+ );
14300
+ }
14301
+ },
13263
14302
  async resolveImage(mediaRef, mimeTypeHinweis) {
13264
14303
  try {
13265
14304
  const bild = await store.resolve(mediaRef, mimeTypeHinweis);
@@ -13272,10 +14311,13 @@ function createHfImageLibrary(options) {
13272
14311
  const id = newImageId();
13273
14312
  try {
13274
14313
  await store.putWithId(id, input.data, input.mime_type, input.title);
13275
- return {
13276
- kind: "ok",
13277
- value: { mediaRef: id, title: input.title, mimeType: input.mime_type, thumbUrl: null }
14314
+ const abgelegt = {
14315
+ mediaRef: id,
14316
+ title: input.title,
14317
+ mimeType: input.mime_type,
14318
+ thumbUrl: null
13278
14319
  };
14320
+ return { kind: "ok", value: abgelegt };
13279
14321
  } catch (error) {
13280
14322
  return fehler2(
13281
14323
  `Das Bild konnte nicht abgelegt werden: ${error instanceof Error ? error.message : String(error)}`,
@@ -13346,7 +14388,7 @@ function createFlowImageProvider(generateImage) {
13346
14388
  }
13347
14389
 
13348
14390
  // src/lib/szenen/imageGenerationOrderStore.ts
13349
- function istText4(wert) {
14391
+ function istText5(wert) {
13350
14392
  return typeof wert === "string" && wert.trim().length > 0;
13351
14393
  }
13352
14394
  function collectImageGenerationOrders(events) {
@@ -13354,7 +14396,7 @@ function collectImageGenerationOrders(events) {
13354
14396
  for (const event of events) {
13355
14397
  if (event.type !== SZENEN_EVENT_TYPES.imageGenerationStarted) continue;
13356
14398
  const payload = event.payload;
13357
- if (!payload || !istText4(payload.generation_batch_id) || !istText4(payload.prompt_run_id)) continue;
14399
+ if (!payload || !istText5(payload.generation_batch_id) || !istText5(payload.prompt_run_id)) continue;
13358
14400
  if (byBatchId.has(payload.generation_batch_id)) continue;
13359
14401
  byBatchId.set(payload.generation_batch_id, {
13360
14402
  generation_batch_id: payload.generation_batch_id,
@@ -13368,7 +14410,7 @@ function collectImageGenerationOrders(events) {
13368
14410
  for (const event of events) {
13369
14411
  if (event.type !== SZENEN_EVENT_TYPES.imageGenerationFinished) continue;
13370
14412
  const payload = event.payload;
13371
- if (!payload || !istText4(payload.generation_batch_id)) continue;
14413
+ if (!payload || !istText5(payload.generation_batch_id)) continue;
13372
14414
  const auftrag = byBatchId.get(payload.generation_batch_id);
13373
14415
  if (!auftrag) continue;
13374
14416
  if (auftrag.status !== "started") continue;
@@ -13392,18 +14434,18 @@ function findImageGenerationOrder(events, batchId) {
13392
14434
  }
13393
14435
 
13394
14436
  // src/lib/szenen/imageBatchStore.ts
13395
- var istText5 = (wert) => typeof wert === "string" && wert.trim().length > 0;
14437
+ var istText6 = (wert) => typeof wert === "string" && wert.trim().length > 0;
13396
14438
  function alsBilder(rohe) {
13397
14439
  if (!Array.isArray(rohe)) return [];
13398
- return rohe.filter((b) => !!b && typeof b === "object").filter((b) => istText5(b.media_ref) && typeof b.position === "number").map((b) => ({
14440
+ return rohe.filter((b) => !!b && typeof b === "object").filter((b) => istText6(b.media_ref) && typeof b.position === "number").map((b) => ({
13399
14441
  media_ref: b.media_ref,
13400
14442
  position: b.position,
13401
- ...istText5(b.asset_id) ? { asset_id: b.asset_id } : {},
14443
+ ...istText6(b.asset_id) ? { asset_id: b.asset_id } : {},
13402
14444
  // Der bestätigte MIME-Typ (Review 2026-08-18 §5 P2) muss durch das
13403
14445
  // Rücklesen hindurch: Genau hier braucht ihn der Lesepfad, um den
13404
14446
  // Dateipfad `images/<id>.<ext>` zu bilden, statt ihn zu erraten. Nur
13405
14447
  // gesetzt, wenn er im Ereignis steht — ältere Batches tragen ihn nicht.
13406
- ...istText5(b.mime_type) ? { mime_type: b.mime_type } : {},
14448
+ ...istText6(b.mime_type) ? { mime_type: b.mime_type } : {},
13407
14449
  model: b.model ?? null,
13408
14450
  seed: b.seed ?? null,
13409
14451
  width: b.width ?? null,
@@ -13415,7 +14457,7 @@ function collectImageBatches(events) {
13415
14457
  for (const event of events) {
13416
14458
  if (event.type !== SZENEN_EVENT_TYPES.imageBatchPersisted) continue;
13417
14459
  const payload = event.payload;
13418
- if (!payload || !istText5(payload.item_id) || !istText5(payload.prompt_run_id) || !istText5(payload.generation_batch_id)) continue;
14460
+ if (!payload || !istText6(payload.item_id) || !istText6(payload.prompt_run_id) || !istText6(payload.generation_batch_id)) continue;
13419
14461
  if (payload.source_kind !== "generated_in_app" && payload.source_kind !== "external_import") continue;
13420
14462
  const bestehend = byItemId.get(payload.item_id);
13421
14463
  if (bestehend?.generation_batch_ids.includes(payload.generation_batch_id)) continue;
@@ -13426,7 +14468,7 @@ function collectImageBatches(events) {
13426
14468
  prompt_run_id: payload.prompt_run_id,
13427
14469
  generation_batch_ids: [payload.generation_batch_id],
13428
14470
  source_kind: payload.source_kind,
13429
- title: istText5(payload.title) ? payload.title : `Batch aus Lauf ${payload.prompt_run_id}`,
14471
+ title: istText6(payload.title) ? payload.title : `Batch aus Lauf ${payload.prompt_run_id}`,
13430
14472
  images: bilder
13431
14473
  });
13432
14474
  continue;
@@ -13903,7 +14945,7 @@ function createFlowSzenenViewPort(options) {
13903
14945
  ...options.now ? { now: options.now } : {}
13904
14946
  }) : void 0;
13905
14947
  const bildProvider = options.imageProvider ?? (options.generateImage ? createFlowImageProvider(options.generateImage) : void 0);
13906
- const bildFaehigkeit = options.imageCapability ?? { environment_id: "flow", execution_paths: [FLOW_EXECUTION_PATH] };
14948
+ const bildFaehigkeit = options.imageCapability ?? { environment_id: "flow", execution_paths: [{ execution_path: FLOW_EXECUTION_PATH, provider: "google" }] };
13907
14949
  const imageGeneration = bildProvider && imageBatchWrite ? createImageGenerationPort({
13908
14950
  runs: { async getRun(runId) {
13909
14951
  return runs.getRun(runId);
@@ -13946,9 +14988,6 @@ export {
13946
14988
  capabilitiesOf,
13947
14989
  unsupportedReason,
13948
14990
  callOptional,
13949
- areasFor,
13950
- resolveArea,
13951
- noticeFor,
13952
14991
  UnsupportedSchemaError,
13953
14992
  compileSchemas,
13954
14993
  validateAgainst,
@@ -13959,8 +14998,12 @@ export {
13959
14998
  validateElementVersion,
13960
14999
  validatePayload,
13961
15000
  formatSchemaErrors,
15001
+ areasFor,
15002
+ resolveArea,
15003
+ noticeFor,
13962
15004
  selectableTargetModels,
13963
15005
  checkImageExecutionProfile,
15006
+ checkImageExecutionProfiles,
13964
15007
  executableImageModels,
13965
15008
  findExecutableImageModel,
13966
15009
  checkImageModelParameters,
@@ -13970,12 +15013,19 @@ export {
13970
15013
  describeTargetModelFailure,
13971
15014
  ALL_PUBLISH_RULES,
13972
15015
  runPublishChecks,
15016
+ PROMPT_RULE_EFFECT,
15017
+ rulesWithoutPromptEffect,
15018
+ diagnosticOfFinding,
15019
+ diagnosticOfSchemaError,
15020
+ promptDiagnosticsOf,
15021
+ describableContent,
13973
15022
  CapabilityAnchorError,
13974
15023
  RULE_SCOPES,
13975
15024
  RULES_WITHOUT_CAPABILITY_EFFECT,
13976
15025
  scopeOfPath,
13977
15026
  capabilityReport,
13978
15027
  unclassifiedPublishRules,
15028
+ sceneOnlyCapabilities,
13979
15029
  resolverFromQueries,
13980
15030
  isProjectionCurrent,
13981
15031
  isOk,
@@ -13995,6 +15045,7 @@ export {
13995
15045
  preferredHeadRevisionOf,
13996
15046
  collectPromptRuns,
13997
15047
  findPromptRun,
15048
+ ladeVorschauen,
13998
15049
  simulatedAnswerFor,
13999
15050
  SIMULATION_PROVIDER,
14000
15051
  createSimulationTextGenerationPort,
@@ -14015,6 +15066,7 @@ export {
14015
15066
  createSimulationSceneDerivationPort,
14016
15067
  runSceneDerivation,
14017
15068
  SzenenView,
15069
+ alsFlowTextZugang,
14018
15070
  createFlowTextGenerationPort,
14019
15071
  CATALOGUE_TYPES,
14020
15072
  publishedHeadsOf,
@@ -14053,8 +15105,10 @@ export {
14053
15105
  ResolveTechnicalError,
14054
15106
  resolveShot,
14055
15107
  resolveShotPayload,
15108
+ resolveScenePayload,
14056
15109
  capabilityGate,
14057
15110
  freezeDraftChain,
15111
+ freezeSceneWorkingState,
14058
15112
  buildSystemInstruction2,
14059
15113
  buildUserPrompt2,
14060
15114
  parseRunResponse,
@@ -14065,6 +15119,8 @@ export {
14065
15119
  bildPfad,
14066
15120
  typAusBytes,
14067
15121
  createHfImageStore,
15122
+ locatorTeile,
15123
+ gruppiereZuItems,
14068
15124
  createHfImageLibrary,
14069
15125
  FLOW_EXECUTION_PATH,
14070
15126
  createFlowImageProvider,