@rslsp1/fa-app-tools 10.0.0 → 10.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/szenen.d.mts CHANGED
@@ -3144,6 +3144,26 @@ interface RequestMoreImagesInput {
3144
3144
  sourceJobId: string;
3145
3145
  /** Wie viele Bilder der **neue** Auftrag anfordert. */
3146
3146
  imageCount: number;
3147
+ /**
3148
+ * Ein **anderes** Zielmodell als das des Ausgangsauftrags (Schritt 06).
3149
+ *
3150
+ * Fehlt es, gilt das des Ausgangsauftrags — das ist der Normalfall und die
3151
+ * Vorbelegung der Oberflaeche. Gesetzt heisst: Der Nutzer hat bewusst
3152
+ * gewechselt. Geprueft wird in beiden Faellen gegen dieselbe heute gueltige
3153
+ * Auswahl; ein gewaehltes Modell wird so wenig geraten wie ein uebernommenes.
3154
+ *
3155
+ * `executionProfileId` gehoert dazu — ein Zielmodell kann mehrere Profile
3156
+ * tragen, und welches gemeint ist, entscheidet nicht der Port.
3157
+ */
3158
+ executionTargetModelKey?: string;
3159
+ executionProfileId?: string;
3160
+ /**
3161
+ * Ein anderes Seitenverhaeltnis. Fehlt es, gilt das des Ausgangsauftrags.
3162
+ *
3163
+ * `null` heisst ausdruecklich **ohne** Seitenverhaeltnis — das ist etwas
3164
+ * anderes als „nicht angegeben" und wird deshalb unterschieden (Regel 4).
3165
+ */
3166
+ aspectRatio?: string | null;
3147
3167
  /** Die Kennung des neuen Auftrags. Ersetzbar, damit ein Test nicht wuerfelt. */
3148
3168
  jobId?: string;
3149
3169
  }
package/dist/szenen.d.ts CHANGED
@@ -3144,6 +3144,26 @@ interface RequestMoreImagesInput {
3144
3144
  sourceJobId: string;
3145
3145
  /** Wie viele Bilder der **neue** Auftrag anfordert. */
3146
3146
  imageCount: number;
3147
+ /**
3148
+ * Ein **anderes** Zielmodell als das des Ausgangsauftrags (Schritt 06).
3149
+ *
3150
+ * Fehlt es, gilt das des Ausgangsauftrags — das ist der Normalfall und die
3151
+ * Vorbelegung der Oberflaeche. Gesetzt heisst: Der Nutzer hat bewusst
3152
+ * gewechselt. Geprueft wird in beiden Faellen gegen dieselbe heute gueltige
3153
+ * Auswahl; ein gewaehltes Modell wird so wenig geraten wie ein uebernommenes.
3154
+ *
3155
+ * `executionProfileId` gehoert dazu — ein Zielmodell kann mehrere Profile
3156
+ * tragen, und welches gemeint ist, entscheidet nicht der Port.
3157
+ */
3158
+ executionTargetModelKey?: string;
3159
+ executionProfileId?: string;
3160
+ /**
3161
+ * Ein anderes Seitenverhaeltnis. Fehlt es, gilt das des Ausgangsauftrags.
3162
+ *
3163
+ * `null` heisst ausdruecklich **ohne** Seitenverhaeltnis — das ist etwas
3164
+ * anderes als „nicht angegeben" und wird deshalb unterschieden (Regel 4).
3165
+ */
3166
+ aspectRatio?: string | null;
3147
3167
  /** Die Kennung des neuen Auftrags. Ersetzbar, damit ein Test nicht wuerfelt. */
3148
3168
  jobId?: string;
3149
3169
  }
package/dist/szenen.js CHANGED
@@ -14550,21 +14550,26 @@ function createImageJobPort(options) {
14550
14550
  retryable: wahl.kind === "error" ? wahl.retryable : true
14551
14551
  };
14552
14552
  }
14553
- const gewaehlt = findExecutableImageModel(
14554
- wahl.value,
14555
- quelle.execution_target_model_key,
14556
- quelle.execution_profile_id
14557
- );
14553
+ const zielModell = input.executionTargetModelKey ?? quelle.execution_target_model_key;
14554
+ const zielProfil = input.executionProfileId ?? quelle.execution_profile_id;
14555
+ if (input.executionTargetModelKey === void 0 !== (input.executionProfileId === void 0)) {
14556
+ return {
14557
+ kind: "rejected",
14558
+ message: `Zielmodell und Ausfuehrungsprofil gehoeren zusammen: Es wurde nur eines von beiden angegeben (Modell "${input.executionTargetModelKey ?? "\u2014"}", Profil "${input.executionProfileId ?? "\u2014"}"). Ein Zielmodell kann mehrere Profile tragen; welches gemeint ist, wird nicht geraten.`
14559
+ };
14560
+ }
14561
+ const gewaehlt = findExecutableImageModel(wahl.value, zielModell, zielProfil);
14558
14562
  if (!gewaehlt) {
14559
14563
  const auswahl = wahl.value.models.map((m) => m.selection_id);
14560
14564
  return {
14561
14565
  kind: "rejected",
14562
- message: `Das Profil "${quelle.execution_profile_id}" von "${quelle.execution_target_model_key}" ist in dieser Umgebung nicht (mehr) ausfuehrbar. Es wird kein Ersatz geraten. ` + (auswahl.length > 0 ? `Ausfuehrbar waeren: ${auswahl.join(", ")} \u2014 bitte den Lauf oeffnen und dort ausdruecklich waehlen.` : `Derzeit ist hier gar kein Bildmodell ausfuehrbar: ${wahl.value.reason ?? "kein sichtbares Zielmodell traegt ein passendes Profil."}`)
14566
+ message: `Das Profil "${zielProfil}" von "${zielModell}" ist in dieser Umgebung nicht (mehr) ausfuehrbar. Es wird kein Ersatz geraten. ` + (auswahl.length > 0 ? `Ausfuehrbar waeren: ${auswahl.join(", ")} \u2014 bitte den Lauf oeffnen und dort ausdruecklich waehlen.` : `Derzeit ist hier gar kein Bildmodell ausfuehrbar: ${wahl.value.reason ?? "kein sichtbares Zielmodell traegt ein passendes Profil."}`)
14563
14567
  };
14564
14568
  }
14569
+ const format = input.aspectRatio === void 0 ? quelle.aspect_ratio ?? null : input.aspectRatio;
14565
14570
  const befunde = checkImageModelParameters(gewaehlt, {
14566
14571
  imageCount,
14567
- ...quelle.aspect_ratio ? { aspectRatio: quelle.aspect_ratio } : {}
14572
+ ...format ? { aspectRatio: format } : {}
14568
14573
  });
14569
14574
  if (befunde.length > 0) {
14570
14575
  return {
@@ -14595,7 +14600,7 @@ function createImageJobPort(options) {
14595
14600
  execution_target_model_key: gewaehlt.target_model_key,
14596
14601
  execution_profile_id: gewaehlt.profile_id,
14597
14602
  image_count: imageCount,
14598
- ...quelle.aspect_ratio ? { aspect_ratio: quelle.aspect_ratio } : {},
14603
+ ...format ? { aspect_ratio: format } : {},
14599
14604
  // **Nicht geraten und nicht erfunden.** Dieser Host kennt keinen
14600
14605
  // Nutzerschluessel — der Flow-Client hat keine Identitaet, nur einen
14601
14606
  // Bestand. Der Fortsetzungsauftrag traegt deshalb den Auftraggeber des
@@ -23421,6 +23426,11 @@ var ImageJobsArea = ({
23421
23426
  const abbruchRef = (0, import_react27.useRef)(false);
23422
23427
  const [einzeln, setEinzeln] = (0, import_react27.useState)(null);
23423
23428
  const [notiz, setNotiz] = (0, import_react27.useState)(null);
23429
+ const [modellLauf, setModellLauf] = (0, import_react27.useState)(null);
23430
+ const wahl = useNachladbareAbfrage(
23431
+ () => port.imageGeneration && modellLauf ? port.imageGeneration.imageModelChoiceForRun(modellLauf) : Promise.resolve({ kind: "ok", value: null }),
23432
+ [port, modellLauf]
23433
+ );
23424
23434
  const liste = useNachladbareAbfrage(
23425
23435
  () => auftraege?.listAllJobs ? auftraege.listAllJobs({ status: filter }) : Promise.resolve({
23426
23436
  kind: "ok",
@@ -23439,8 +23449,13 @@ var ImageJobsArea = ({
23439
23449
  const seite = liste.wert;
23440
23450
  const eintraege = seite?.eintraege ?? [];
23441
23451
  const offen = seite?.offen ?? 0;
23452
+ const ersterLauf = eintraege[0]?.job.prompt_run_id ?? null;
23453
+ (0, import_react27.useEffect)(() => {
23454
+ if (modellLauf === null && ersterLauf !== null) setModellLauf(ersterLauf);
23455
+ }, [modellLauf, ersterLauf]);
23442
23456
  const queueLaeuft = lauf !== null && (lauf.zustand === "laeuft" || lauf.zustand === "pause");
23443
- async function einzelStart(jobId) {
23457
+ const eigeneLaufend = (einzeln !== null ? 1 : 0) + (queueLaeuft && lauf?.aktuell && lauf.aktuell !== einzeln ? 1 : 0);
23458
+ async function einzelStart(jobId, vorspann = "") {
23444
23459
  if (!auftraege || laeuftRef.current || einzeln !== null) return;
23445
23460
  setEinzeln(jobId);
23446
23461
  setNotiz(null);
@@ -23449,7 +23464,7 @@ var ImageJobsArea = ({
23449
23464
  if (ergebnis.kind === "ok") {
23450
23465
  setNotiz({
23451
23466
  tone: ergebnis.job.status === "succeeded" ? "ok" : "rejected",
23452
- text: `Auftrag ${jobId}: ${STATUS_TEXT2[ergebnis.job.status]}.` + (ergebnis.job.diagnostic ? ` ${ergebnis.job.diagnostic}` : "")
23467
+ text: `${vorspann}Auftrag ${jobId}: ${STATUS_TEXT2[ergebnis.job.status]}.` + (ergebnis.job.diagnostic ? ` ${ergebnis.job.diagnostic}` : "")
23453
23468
  });
23454
23469
  } else if (ergebnis.kind === "lost" || ergebnis.kind === "rejected") {
23455
23470
  setNotiz({ tone: "rejected", text: ergebnis.message });
@@ -23466,6 +23481,46 @@ var ImageJobsArea = ({
23466
23481
  neuLesen();
23467
23482
  }
23468
23483
  }
23484
+ async function erzeugenUndStarten(quelle, wieViele, modell) {
23485
+ const anfordern = auftraege?.requestMoreImages;
23486
+ if (!anfordern || laeuftRef.current || einzeln !== null) return;
23487
+ setNotiz(null);
23488
+ let neuer;
23489
+ try {
23490
+ const ergebnis = await anfordern({
23491
+ sourceJobId: quelle.job_id,
23492
+ imageCount: wieViele,
23493
+ // Nur mitgeben, wenn wirklich gewechselt wurde — sonst gilt der
23494
+ // Ausgangsauftrag, und das steht so im Port.
23495
+ ...modell && (modell.target_model_key !== quelle.execution_target_model_key || modell.profile_id !== quelle.execution_profile_id) ? {
23496
+ executionTargetModelKey: modell.target_model_key,
23497
+ executionProfileId: modell.profile_id
23498
+ // Ein Formatwechsel ist nicht gefragt; traegt das neue
23499
+ // Modell das alte Format nicht, lehnt der Port ab und
23500
+ // sagt warum, statt still zu ersetzen.
23501
+ } : {}
23502
+ });
23503
+ if (ergebnis.kind !== "ok") {
23504
+ setNotiz({
23505
+ tone: ergebnis.kind === "rejected" ? "rejected" : "error",
23506
+ text: ergebnis.message
23507
+ });
23508
+ return;
23509
+ }
23510
+ neuer = ergebnis.job;
23511
+ } catch (e) {
23512
+ setNotiz({
23513
+ tone: "error",
23514
+ text: `Der neue Bildauftrag zu ${quelle.job_id} konnte nicht angelegt werden: ${e instanceof Error ? e.message : String(e)}`
23515
+ });
23516
+ return;
23517
+ }
23518
+ neuLesen();
23519
+ await einzelStart(
23520
+ neuer.job_id,
23521
+ `Neuer Auftrag \xFCber ${neuer.image_count} ${neuer.image_count === 1 ? "Bild" : "Bilder"} mit ${neuer.execution_target_model_key}; `
23522
+ );
23523
+ }
23469
23524
  async function alleOffenenStarten() {
23470
23525
  if (!auftraege?.listAllJobs || laeuftRef.current) return;
23471
23526
  laeuftRef.current = true;
@@ -23518,7 +23573,26 @@ var ImageJobsArea = ({
23518
23573
  children: "\u27F3 Aktualisieren"
23519
23574
  }
23520
23575
  ),
23521
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "data-testid": "bildauftraege-zuletzt", children: zuletzt ? `zuletzt aktualisiert ${zuletzt}` : "noch nicht aktualisiert" })
23576
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { "data-testid": "bildauftraege-zuletzt", children: zuletzt ? `zuletzt aktualisiert ${zuletzt}` : "noch nicht aktualisiert" }),
23577
+ eigeneLaufend > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
23578
+ "span",
23579
+ {
23580
+ className: "szenen-bildauftraege__laufzaehler",
23581
+ "data-testid": "bildauftraege-laufzaehler",
23582
+ title: `${eigeneLaufend} Auftrag${eigeneLaufend === 1 ? "" : "e"} dieses Tabs l\xE4uft gerade`,
23583
+ children: [
23584
+ "\u27F3 ",
23585
+ eigeneLaufend,
23586
+ " l\xE4uft",
23587
+ eigeneLaufend === 1 ? "" : "en"
23588
+ ]
23589
+ }
23590
+ )
23591
+ ] }),
23592
+ (wahl.wert?.invalid_profiles.length ?? 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { role: "alert", "data-testid": "bildauftraege-profilbefunde", children: [
23593
+ "Nicht angeboten, weil das Profil unvollst\xE4ndig ist:",
23594
+ " ",
23595
+ wahl.wert.invalid_profiles.join(" \xB7 ")
23522
23596
  ] }),
23523
23597
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23524
23598
  Bildkontrolle,
@@ -23611,10 +23685,9 @@ var ImageJobsArea = ({
23611
23685
  gesperrt: queueLaeuft || einzeln !== null,
23612
23686
  laufend: einzeln === eintrag.job.job_id || lauf?.aktuell === eintrag.job.job_id,
23613
23687
  onStart: () => void einzelStart(eintrag.job.job_id),
23614
- onAngelegt: (text) => {
23615
- setNotiz({ tone: "ok", text });
23616
- neuLesen();
23617
- },
23688
+ onErzeugen: (anzahl, modell) => erzeugenUndStarten(eintrag.job, anzahl, modell),
23689
+ modelle: wahl.wert?.models ?? null,
23690
+ modelleLaden: wahl.wert === null && wahl.fehler === null,
23618
23691
  ...onPromptOeffnen ? { onPromptOeffnen } : {}
23619
23692
  },
23620
23693
  eintrag.job.job_id
@@ -23666,12 +23739,13 @@ var AuftragsZeile = ({
23666
23739
  gesperrt,
23667
23740
  laufend,
23668
23741
  onStart,
23669
- onAngelegt,
23670
- onPromptOeffnen
23742
+ onErzeugen,
23743
+ onPromptOeffnen,
23744
+ modelle,
23745
+ modelleLaden
23671
23746
  }) => {
23672
23747
  const { job, herkunft } = eintrag;
23673
23748
  const [ergebnisOffen, setErgebnisOffen] = (0, import_react27.useState)(false);
23674
- const [weitereOffen, setWeitereOffen] = (0, import_react27.useState)(false);
23675
23749
  const hatErgebnis = Boolean(job.generation_batch_id) && (job.status === "succeeded" || job.status === "partial");
23676
23750
  const kannWeitere = Boolean(port.imageJobs?.requestMoreImages) && istAbgeschlossen(job);
23677
23751
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
@@ -23683,6 +23757,12 @@ var AuftragsZeile = ({
23683
23757
  children: [
23684
23758
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { className: "szenen-bildauftraege__kopf", children: [
23685
23759
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("strong", { "data-testid": `bildauftrag-status-${job.job_id}`, children: STATUS_TEXT2[job.status] }),
23760
+ " \xB7 ",
23761
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("strong", { "data-testid": `bildauftrag-anzahl-${job.job_id}`, children: [
23762
+ job.image_count,
23763
+ " ",
23764
+ job.image_count === 1 ? "Bild" : "Bilder"
23765
+ ] }),
23686
23766
  " \u2014 ",
23687
23767
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { children: herkunft.szene_titel ?? (herkunft.lauf_gefunden ? "Lauf ohne benennbares Element" : "Lauf nicht in diesem Bestand") })
23688
23768
  ] }),
@@ -23699,11 +23779,6 @@ var AuftragsZeile = ({
23699
23779
  "Profil ",
23700
23780
  /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("code", { children: job.execution_profile_id })
23701
23781
  ] }),
23702
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { children: [
23703
- job.image_count,
23704
- " ",
23705
- job.image_count === 1 ? "Bild" : "Bilder"
23706
- ] }),
23707
23782
  /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { children: [
23708
23783
  "Format ",
23709
23784
  job.aspect_ratio ?? "\u2014"
@@ -23738,7 +23813,7 @@ var AuftragsZeile = ({
23738
23813
  "data-testid": `bildauftrag-start-${job.job_id}`,
23739
23814
  disabled: gesperrt,
23740
23815
  onClick: onStart,
23741
- children: laufend ? "L\xE4uft \u2026" : "Start (kostet einen Bildaufruf)"
23816
+ children: laufend ? "L\xE4uft \u2026" : "Start"
23742
23817
  }
23743
23818
  ),
23744
23819
  onPromptOeffnen && herkunft.lauf_gefunden && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
@@ -23758,18 +23833,18 @@ var AuftragsZeile = ({
23758
23833
  onClick: () => setErgebnisOffen((o) => !o),
23759
23834
  children: ergebnisOffen ? "Ergebnisse ausblenden" : "Ergebnisse ansehen"
23760
23835
  }
23761
- ),
23762
- kannWeitere && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23763
- "button",
23764
- {
23765
- type: "button",
23766
- "data-testid": `bildauftrag-weitere-${job.job_id}`,
23767
- onClick: () => setWeitereOffen((o) => !o),
23768
- children: weitereOffen ? "Weitere Bilder schlie\xDFen" : "Weitere Bilder"
23769
- }
23770
23836
  )
23771
23837
  ] }),
23772
- kannWeitere && weitereOffen && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(WeitereBilder, { port, job, onAngelegt }),
23838
+ kannWeitere && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23839
+ WeitereBilder,
23840
+ {
23841
+ job,
23842
+ gesperrt,
23843
+ modelle,
23844
+ modelleLaden,
23845
+ onErzeugen
23846
+ }
23847
+ ),
23773
23848
  ergebnisOffen && job.generation_batch_id && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23774
23849
  AuftragsErgebnis,
23775
23850
  {
@@ -23782,123 +23857,106 @@ var AuftragsZeile = ({
23782
23857
  }
23783
23858
  );
23784
23859
  };
23785
- var WeitereBilder = ({ port, job, onAngelegt }) => {
23860
+ var WeitereBilder = ({ job, gesperrt, modelle, modelleLaden, onErzeugen }) => {
23786
23861
  const [anzahl, setAnzahl] = (0, import_react27.useState)(1);
23862
+ const [wahlId, setWahlId] = (0, import_react27.useState)(null);
23787
23863
  const [laeuft, setLaeuft] = (0, import_react27.useState)(false);
23788
23864
  const [notiz, setNotiz] = (0, import_react27.useState)(null);
23789
- const wahl = useNachladbareAbfrage(
23790
- () => port.imageGeneration ? port.imageGeneration.imageModelChoiceForRun(job.prompt_run_id) : Promise.resolve({ kind: "ok", value: null }),
23791
- [port, job.prompt_run_id]
23792
- );
23793
- const gewaehlt = wahl.wert ? findExecutableImageModel(
23794
- wahl.wert,
23795
- job.execution_target_model_key,
23796
- job.execution_profile_id
23797
- ) : null;
23798
- const maxBilder = gewaehlt?.max_images ?? null;
23799
- const anlegen = async (wieViele) => {
23800
- const anfordern = port.imageJobs?.requestMoreImages;
23801
- if (!anfordern || laeuft) return;
23865
+ const uebernommen = modelle ? modelle.find((m) => m.target_model_key === job.execution_target_model_key && m.profile_id === job.execution_profile_id) ?? null : null;
23866
+ const aktiv = wahlId && modelle?.find((m) => m.selection_id === wahlId) || uebernommen;
23867
+ const maxBilder = aktiv?.max_images ?? 1;
23868
+ const starten = async (wieViele) => {
23869
+ if (laeuft || gesperrt || !aktiv) return;
23802
23870
  setLaeuft(true);
23803
23871
  setNotiz(null);
23804
23872
  try {
23805
- const ergebnis = await anfordern({
23806
- sourceJobId: job.job_id,
23807
- imageCount: wieViele
23808
- });
23809
- if (ergebnis.kind === "ok") {
23810
- onAngelegt(
23811
- `Neuer Bildauftrag ${ergebnis.job.job_id} f\xFCr Promptlauf ${ergebnis.job.prompt_run_id}: ${ergebnis.job.image_count} ${ergebnis.job.image_count === 1 ? "Bild" : "Bilder"} mit ${ergebnis.job.execution_target_model_key} (Profil ${ergebnis.job.execution_profile_id}). Auftrag ${job.job_id} bleibt unver\xE4ndert abgeschlossen.`
23812
- );
23813
- } else {
23814
- setNotiz({
23815
- tone: ergebnis.kind === "rejected" ? "rejected" : "error",
23816
- text: ergebnis.message
23817
- });
23818
- }
23873
+ await onErzeugen(wieViele, aktiv);
23819
23874
  } catch (e) {
23820
23875
  setNotiz({
23821
23876
  tone: "error",
23822
- text: `Der neue Bildauftrag zu ${job.job_id} konnte nicht angelegt werden: ` + (e instanceof Error ? e.message : String(e))
23877
+ text: `Weitere Bilder zu ${job.job_id} sind gescheitert: ` + (e instanceof Error ? e.message : String(e))
23823
23878
  });
23824
23879
  } finally {
23825
23880
  setLaeuft(false);
23826
23881
  }
23827
23882
  };
23883
+ if (modelleLaden && modelle === null) {
23884
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23885
+ "p",
23886
+ {
23887
+ className: "szenen-bildauftraege__weitere",
23888
+ "data-testid": `bildauftrag-weitere-laden-${job.job_id}`,
23889
+ children: "Bildmodelle werden gepr\xFCft \u2026"
23890
+ }
23891
+ );
23892
+ }
23893
+ if (modelle !== null && modelle.length === 0) {
23894
+ return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23895
+ "p",
23896
+ {
23897
+ className: "szenen-bildauftraege__weitere",
23898
+ role: "alert",
23899
+ "data-testid": `bildauftrag-weitere-keine-${job.job_id}`,
23900
+ children: "Hier ist derzeit kein Bildmodell ausf\xFChrbar \u2014 weitere Bilder sind nicht m\xF6glich. Es wird kein Ersatz geraten."
23901
+ }
23902
+ );
23903
+ }
23828
23904
  return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
23829
- "section",
23905
+ "p",
23830
23906
  {
23831
23907
  className: "szenen-bildauftraege__weitere",
23832
23908
  "data-testid": `bildauftrag-weitere-panel-${job.job_id}`,
23833
- "aria-label": "Weitere Bilder",
23834
23909
  children: [
23835
- wahl.fehler && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { role: "alert", "data-testid": `bildauftrag-weitere-fehler-${job.job_id}`, children: [
23836
- "Die ausf\xFChrbaren Bildmodelle waren nicht lesbar: ",
23837
- wahl.fehler
23838
- ] }),
23839
- wahl.laedt && wahl.wert === null && !wahl.fehler && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { "data-testid": `bildauftrag-weitere-laden-${job.job_id}`, children: "Profil wird gepr\xFCft \u2026" }),
23840
- wahl.wert !== null && !gewaehlt && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { role: "alert", "data-testid": `bildauftrag-weitere-ungueltig-${job.job_id}`, children: [
23841
- "Das Profil ",
23842
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("code", { children: job.execution_profile_id }),
23843
- " von",
23844
- " ",
23845
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("code", { children: job.execution_target_model_key }),
23846
- " ist hier nicht mehr ausf\xFChrbar. Es wird kein Ersatz geraten \u2014",
23847
- " ",
23848
- wahl.wert.models.length > 0 ? `ausf\xFChrbar w\xE4ren: ${wahl.wert.models.map((m) => m.selection_id).join(", ")}. Bitte den Promptlauf \xF6ffnen und dort ausdr\xFCcklich w\xE4hlen.` : `derzeit ist hier gar kein Bildmodell ausf\xFChrbar: ${wahl.wert.reason ?? "kein sichtbares Zielmodell tr\xE4gt ein passendes Profil."}`
23849
- ] }),
23850
- gewaehlt && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
23851
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { "data-testid": `bildauftrag-weitere-profil-${job.job_id}`, children: [
23852
- gewaehlt.display_name,
23853
- " bei ",
23854
- gewaehlt.provider,
23855
- " \xB7 bis zu",
23856
- " ",
23857
- gewaehlt.max_images,
23858
- " Bilder je Auftrag \xB7 Format",
23859
- " ",
23860
- job.aspect_ratio ?? "\u2014"
23861
- ] }),
23862
- /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("p", { className: "szenen-bildauftraege__aktionen", children: [
23863
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23864
- "button",
23865
- {
23866
- type: "button",
23867
- "data-testid": `bildauftrag-plus1-${job.job_id}`,
23868
- disabled: laeuft,
23869
- onClick: () => void anlegen(1),
23870
- children: "+1 Bild"
23871
- }
23872
- ),
23873
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: `bildauftrag-weitere-anzahl-${job.job_id}`, children: "Anzahl" }),
23874
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23875
- "select",
23876
- {
23877
- id: `bildauftrag-weitere-anzahl-${job.job_id}`,
23878
- "data-testid": `bildauftrag-weitere-anzahl-${job.job_id}`,
23879
- value: anzahl,
23880
- disabled: laeuft,
23881
- onChange: (e) => setAnzahl(Number(e.target.value)),
23882
- children: Array.from(
23883
- { length: Math.max(1, maxBilder ?? 1) },
23884
- (_, i) => i + 1
23885
- ).map((n) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: n, children: n }, n))
23886
- }
23887
- ),
23888
- /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23889
- "button",
23890
- {
23891
- type: "button",
23892
- "data-testid": `bildauftrag-weitere-start-${job.job_id}`,
23893
- disabled: laeuft,
23894
- onClick: () => void anlegen(anzahl),
23895
- children: laeuft ? "Wird angelegt \u2026" : "Erzeugen"
23896
- }
23897
- )
23898
- ] })
23899
- ] }),
23910
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: `bildauftrag-modell-${job.job_id}`, children: "Weitere Bilder mit" }),
23911
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
23912
+ "select",
23913
+ {
23914
+ id: `bildauftrag-modell-${job.job_id}`,
23915
+ "data-testid": `bildauftrag-modell-${job.job_id}`,
23916
+ value: aktiv?.selection_id ?? "",
23917
+ disabled: laeuft || gesperrt,
23918
+ onChange: (e) => {
23919
+ setWahlId(e.target.value);
23920
+ setNotiz(null);
23921
+ },
23922
+ children: [
23923
+ !aktiv && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("option", { value: "", children: [
23924
+ job.execution_profile_id,
23925
+ " von ",
23926
+ job.execution_target_model_key,
23927
+ " \u2014 nicht mehr ausf\xFChrbar, bitte w\xE4hlen"
23928
+ ] }),
23929
+ (modelle ?? []).map((m) => /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("option", { value: m.selection_id, children: [
23930
+ m.display_name,
23931
+ m.target_model_key === job.execution_target_model_key && m.profile_id === job.execution_profile_id ? " (wie gehabt)" : ""
23932
+ ] }, m.selection_id))
23933
+ ]
23934
+ }
23935
+ ),
23936
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("label", { htmlFor: `bildauftrag-weitere-anzahl-${job.job_id}`, children: "\xD7" }),
23937
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23938
+ "select",
23939
+ {
23940
+ id: `bildauftrag-weitere-anzahl-${job.job_id}`,
23941
+ "data-testid": `bildauftrag-weitere-anzahl-${job.job_id}`,
23942
+ value: Math.min(anzahl, maxBilder),
23943
+ disabled: laeuft || gesperrt || !aktiv,
23944
+ onChange: (e) => setAnzahl(Number(e.target.value)),
23945
+ children: Array.from({ length: Math.max(1, maxBilder) }, (_, i) => i + 1).map((n) => /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("option", { value: n, children: n }, n))
23946
+ }
23947
+ ),
23948
+ /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23949
+ "button",
23950
+ {
23951
+ type: "button",
23952
+ "data-testid": `bildauftrag-weitere-start-${job.job_id}`,
23953
+ disabled: laeuft || gesperrt || !aktiv,
23954
+ onClick: () => void starten(Math.min(anzahl, maxBilder)),
23955
+ children: laeuft ? "L\xE4uft \u2026" : "Erzeugen"
23956
+ }
23957
+ ),
23900
23958
  notiz && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
23901
- "p",
23959
+ "span",
23902
23960
  {
23903
23961
  role: notiz.tone === "error" ? "alert" : void 0,
23904
23962
  "data-testid": `bildauftrag-weitere-notiz-${job.job_id}`,
package/dist/szenen.mjs CHANGED
@@ -220,7 +220,7 @@ import {
220
220
  validateElementVersion,
221
221
  validatePayload,
222
222
  withReference
223
- } from "./chunk-UDBGDCKI.mjs";
223
+ } from "./chunk-5SYVLULG.mjs";
224
224
  import {
225
225
  ContractViolation,
226
226
  STYLE_PAYLOAD,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rslsp1/fa-app-tools",
3
- "version": "10.0.0",
3
+ "version": "10.1.3",
4
4
  "description": "Shared tools and hooks for Fine Art flow apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",