@rslsp1/fa-app-tools 2.0.81 → 2.0.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-GEGJD43Y.mjs → chunk-JTGC5PXJ.mjs} +602 -10
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +737 -67
- package/dist/index.mjs +148 -58
- package/dist/szenen.d.mts +183 -8
- package/dist/szenen.d.ts +183 -8
- package/dist/szenen.js +388 -28
- package/dist/szenen.mjs +47 -258
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -786,7 +786,7 @@ __export(index_exports, {
|
|
|
786
786
|
module.exports = __toCommonJS(index_exports);
|
|
787
787
|
|
|
788
788
|
// package.json
|
|
789
|
-
var version = "2.0.
|
|
789
|
+
var version = "2.0.83";
|
|
790
790
|
|
|
791
791
|
// src/hooks/useOnClickOutside.ts
|
|
792
792
|
var import_react = require("react");
|
|
@@ -3692,6 +3692,21 @@ function validateTagBaseSelection(base, userId, contextId) {
|
|
|
3692
3692
|
// src/hooks/useTagBase.ts
|
|
3693
3693
|
var USER_ID_KEY = "aa-user-id";
|
|
3694
3694
|
var CONTEXT_ID_KEY = "aa-context-id";
|
|
3695
|
+
var IDENTITY_NAMESPACE_KEY = "aa-identity-namespace";
|
|
3696
|
+
function readStoredNamespace() {
|
|
3697
|
+
try {
|
|
3698
|
+
return localStorage.getItem(IDENTITY_NAMESPACE_KEY);
|
|
3699
|
+
} catch {
|
|
3700
|
+
return null;
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
function writeStoredNamespace(namespace) {
|
|
3704
|
+
try {
|
|
3705
|
+
if (namespace === null) localStorage.removeItem(IDENTITY_NAMESPACE_KEY);
|
|
3706
|
+
else localStorage.setItem(IDENTITY_NAMESPACE_KEY, namespace);
|
|
3707
|
+
} catch {
|
|
3708
|
+
}
|
|
3709
|
+
}
|
|
3695
3710
|
function readStoredId(key) {
|
|
3696
3711
|
try {
|
|
3697
3712
|
const v = localStorage.getItem(key);
|
|
@@ -3728,6 +3743,16 @@ function useTagBase(token, namespace) {
|
|
|
3728
3743
|
}, [selectedContextId]);
|
|
3729
3744
|
const load = (0, import_react19.useCallback)(async () => {
|
|
3730
3745
|
if (!token || !namespace) return;
|
|
3746
|
+
if (readStoredNamespace() !== namespace) {
|
|
3747
|
+
selectedUserIdRef.current = null;
|
|
3748
|
+
selectedContextIdRef.current = null;
|
|
3749
|
+
setSelectedUserId(null);
|
|
3750
|
+
setSelectedContextId(null);
|
|
3751
|
+
writeStoredId(USER_ID_KEY, null);
|
|
3752
|
+
writeStoredId(CONTEXT_ID_KEY, null);
|
|
3753
|
+
writeStoredNamespace(namespace);
|
|
3754
|
+
setPickerMessage(null);
|
|
3755
|
+
}
|
|
3731
3756
|
setIsLoading(true);
|
|
3732
3757
|
setError(null);
|
|
3733
3758
|
try {
|
|
@@ -3766,16 +3791,19 @@ function useTagBase(token, namespace) {
|
|
|
3766
3791
|
setSelectedContextId(null);
|
|
3767
3792
|
writeStoredId(USER_ID_KEY, userId);
|
|
3768
3793
|
writeStoredId(CONTEXT_ID_KEY, null);
|
|
3769
|
-
|
|
3794
|
+
writeStoredNamespace(namespace);
|
|
3795
|
+
}, [namespace]);
|
|
3770
3796
|
const selectContext = (0, import_react19.useCallback)((contextId) => {
|
|
3771
3797
|
setSelectedContextId(contextId);
|
|
3772
3798
|
writeStoredId(CONTEXT_ID_KEY, contextId);
|
|
3773
|
-
|
|
3799
|
+
writeStoredNamespace(namespace);
|
|
3800
|
+
}, [namespace]);
|
|
3774
3801
|
const resetSelection = (0, import_react19.useCallback)(() => {
|
|
3775
3802
|
setSelectedUserId(null);
|
|
3776
3803
|
setSelectedContextId(null);
|
|
3777
3804
|
writeStoredId(USER_ID_KEY, null);
|
|
3778
3805
|
writeStoredId(CONTEXT_ID_KEY, null);
|
|
3806
|
+
writeStoredNamespace(null);
|
|
3779
3807
|
setPickerMessage(null);
|
|
3780
3808
|
}, []);
|
|
3781
3809
|
const validation = tagBase ? validateTagBaseSelection(tagBase, selectedUserId, selectedContextId) : { valid: false, reason: null };
|
|
@@ -6565,13 +6593,13 @@ function noticeFor(ergebnis, was) {
|
|
|
6565
6593
|
};
|
|
6566
6594
|
}
|
|
6567
6595
|
case "rejected": {
|
|
6568
|
-
const
|
|
6596
|
+
const fehler4 = ergebnis.errors ?? [];
|
|
6569
6597
|
const ungeprueft = ergebnis.unchecked ?? [];
|
|
6570
6598
|
return {
|
|
6571
6599
|
tone: "rejected",
|
|
6572
|
-
text: `${was}: abgelehnt \u2014 ${
|
|
6600
|
+
text: `${was}: abgelehnt \u2014 ${fehler4.length} Befund${fehler4.length === 1 ? "" : "e"}.`,
|
|
6573
6601
|
details: [
|
|
6574
|
-
...
|
|
6602
|
+
...fehler4.map((f) => `${f.path ?? "(ohne Pfad)"}: ${f.message ?? "ohne Meldung"}`),
|
|
6575
6603
|
// Nicht verschweigen: was nicht geprüft wurde, ist nicht in Ordnung,
|
|
6576
6604
|
// sondern ungeprüft.
|
|
6577
6605
|
...ungeprueft.map((u) => `ungepr\xFCft: ${u}`)
|
|
@@ -11266,7 +11294,7 @@ var ERKLAERUNG = {
|
|
|
11266
11294
|
};
|
|
11267
11295
|
var CapabilityPanel = ({ port, elementId, setupPayload }) => {
|
|
11268
11296
|
const [bericht, setBericht] = (0, import_react36.useState)(null);
|
|
11269
|
-
const [
|
|
11297
|
+
const [fehler4, setFehler] = (0, import_react36.useState)(null);
|
|
11270
11298
|
(0, import_react36.useEffect)(() => {
|
|
11271
11299
|
let abgemeldet = false;
|
|
11272
11300
|
setBericht(null);
|
|
@@ -11288,10 +11316,10 @@ var CapabilityPanel = ({ port, elementId, setupPayload }) => {
|
|
|
11288
11316
|
abgemeldet = true;
|
|
11289
11317
|
};
|
|
11290
11318
|
}, [port, elementId, setupPayload]);
|
|
11291
|
-
if (
|
|
11319
|
+
if (fehler4) {
|
|
11292
11320
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { "data-testid": "capability-fehler", role: "alert", children: [
|
|
11293
11321
|
"F\xE4higkeitsbericht nicht erstellbar: ",
|
|
11294
|
-
|
|
11322
|
+
fehler4
|
|
11295
11323
|
] });
|
|
11296
11324
|
}
|
|
11297
11325
|
if (!bericht) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { "data-testid": "capability-laden", children: "F\xE4higkeitsbericht wird erstellt \u2026" });
|
|
@@ -11401,6 +11429,10 @@ var ChainPromptAction = ({
|
|
|
11401
11429
|
var import_react39 = require("react");
|
|
11402
11430
|
|
|
11403
11431
|
// src/lib/szenen/itemDerivation.ts
|
|
11432
|
+
var SZENEN_ITEM_PREFIX = "szn-";
|
|
11433
|
+
function itemIdForRun(runId) {
|
|
11434
|
+
return `${SZENEN_ITEM_PREFIX}${runId}`;
|
|
11435
|
+
}
|
|
11404
11436
|
function roundOfRun(run, runsOfShot) {
|
|
11405
11437
|
return runsOfShot.findIndex((kandidat) => kandidat.run_id === run.run_id) + 1;
|
|
11406
11438
|
}
|
|
@@ -11502,7 +11534,30 @@ var SZENEN_EVENT_TYPES = {
|
|
|
11502
11534
|
* ebenfalls keine Bilddaten — nur Status, Zaehlung und die Item-Kennung,
|
|
11503
11535
|
* falls eine entstand.
|
|
11504
11536
|
*/
|
|
11505
|
-
imageGenerationFinished: "szenen.image_generation_finished"
|
|
11537
|
+
imageGenerationFinished: "szenen.image_generation_finished",
|
|
11538
|
+
/**
|
|
11539
|
+
* Ein Bild-Batch ist kanonisch gespeichert — Stufe 6.9.2, Gate D
|
|
11540
|
+
* (D-6.9.2-6).
|
|
11541
|
+
*
|
|
11542
|
+
* Erscheint erst, **nachdem** jedes Bild des Batches im Bildbestand liegt
|
|
11543
|
+
* (`hfUploadImage` + `image_added`, dieselbe Reihenfolge wie
|
|
11544
|
+
* `hfImageLibrary.putImage`) — kein Bild gilt als vorhanden, bevor sein
|
|
11545
|
+
* Upload bestätigt ist (R3). Trägt bewusst **keine Bilddaten**, nur den
|
|
11546
|
+
* vollständigen Metadatennachweis, den `listBatchesForPromptRun()` /
|
|
11547
|
+
* `getBatch()` ohne MySQL rekonstruieren können müssen: `item_id`,
|
|
11548
|
+
* `prompt_run_id`, `generation_batch_id`, `source_kind`, je Bild
|
|
11549
|
+
* `position`, `media_ref`, `asset_id`, `model`, `seed`, `width`/`height`.
|
|
11550
|
+
*
|
|
11551
|
+
* Additiv wie jedes Ereignis dieser Domain: ein zweiter Batch desselben
|
|
11552
|
+
* Laufs ist ein **weiteres** Ereignis mit derselben `item_id`, nicht eine
|
|
11553
|
+
* Änderung am ersten (D-113/D-121 — ein Lauf bleibt ein Item). Gilt für
|
|
11554
|
+
* `generated_in_app` **und** `external_import` — nur `source_kind`
|
|
11555
|
+
* unterscheidet die beiden Schreiber (D-116/D-117/D-120).
|
|
11556
|
+
*
|
|
11557
|
+
* Der Elementreducer ignoriert auch diesen Typ (`default:`-Zweig); gelesen
|
|
11558
|
+
* wird mit `collectImageBatches` (`imageBatchStore.ts`).
|
|
11559
|
+
*/
|
|
11560
|
+
imageBatchPersisted: "szenen.image_batch_persisted"
|
|
11506
11561
|
};
|
|
11507
11562
|
function sortForReplay(events) {
|
|
11508
11563
|
return [...events].sort((a, b) => {
|
|
@@ -12151,10 +12206,10 @@ var ZuordnenAktion = ({ port, lauf, onFertig }) => {
|
|
|
12151
12206
|
setNotiz(
|
|
12152
12207
|
ergebnis.kind === "ok" ? { tone: "ok", text: `Importiert als Item ${ergebnis.value.item_id} mit ${bilder.length} Bild(ern).` } : noticeFor(ergebnis, "Externe Bilder importieren")
|
|
12153
12208
|
);
|
|
12154
|
-
} catch (
|
|
12209
|
+
} catch (fehler4) {
|
|
12155
12210
|
setNotiz({
|
|
12156
12211
|
tone: "error",
|
|
12157
|
-
text: `Externe Bilder importieren: ${
|
|
12212
|
+
text: `Externe Bilder importieren: ${fehler4 instanceof Error ? fehler4.message : String(fehler4)}`
|
|
12158
12213
|
});
|
|
12159
12214
|
}
|
|
12160
12215
|
setLaeuft(false);
|
|
@@ -17464,6 +17519,531 @@ function createHfImageLibrary(options) {
|
|
|
17464
17519
|
};
|
|
17465
17520
|
}
|
|
17466
17521
|
|
|
17522
|
+
// src/lib/szenen/flowImageProvider.ts
|
|
17523
|
+
var FLOW_MODEL_DISPLAY_NAMES = {
|
|
17524
|
+
"imagen-4.0-generate-001": "Imagen 4"
|
|
17525
|
+
};
|
|
17526
|
+
function flowImageProviderHasAccess(model) {
|
|
17527
|
+
return model.callable_model_id in FLOW_MODEL_DISPLAY_NAMES;
|
|
17528
|
+
}
|
|
17529
|
+
function istNichtleererText(wert) {
|
|
17530
|
+
return typeof wert === "string" && wert.trim().length > 0;
|
|
17531
|
+
}
|
|
17532
|
+
function createFlowImageProvider(generateImage) {
|
|
17533
|
+
return {
|
|
17534
|
+
async generate(input) {
|
|
17535
|
+
const modelDisplayName = FLOW_MODEL_DISPLAY_NAMES[input.callableModelId];
|
|
17536
|
+
if (!modelDisplayName) {
|
|
17537
|
+
throw new Error(
|
|
17538
|
+
`Der Flow-Host kennt keinen Flow-Display-Namen zu "${input.callableModelId}". Bekannt sind: ${Object.keys(FLOW_MODEL_DISPLAY_NAMES).join(", ")}. Es wird kein anderes Modell ersatzweise gerufen (D-115/D-6.9.2-3).`
|
|
17539
|
+
);
|
|
17540
|
+
}
|
|
17541
|
+
if (istNichtleererText(input.negativePrompt)) {
|
|
17542
|
+
throw new Error(
|
|
17543
|
+
"Flow.generate.image kennt keinen dokumentierten Parameter f\xFCr einen negativen Prompt. Der Auftrag wird deshalb als fehlgeschlagen protokolliert, statt den negativen Prompt still zu verlieren (D-6.9.2-3)."
|
|
17544
|
+
);
|
|
17545
|
+
}
|
|
17546
|
+
const erzeugt = [];
|
|
17547
|
+
let ersterFehler = null;
|
|
17548
|
+
for (let position = 0; position < input.imageCount; position++) {
|
|
17549
|
+
try {
|
|
17550
|
+
const antwort = await generateImage({
|
|
17551
|
+
prompt: input.positivePrompt,
|
|
17552
|
+
modelDisplayName,
|
|
17553
|
+
...input.aspectRatio ? { aspectRatio: input.aspectRatio } : {}
|
|
17554
|
+
});
|
|
17555
|
+
if (!antwort || typeof antwort.base64 !== "string" || antwort.base64.length === 0) {
|
|
17556
|
+
throw new Error("Flow.generate.image hat kein Bild geliefert.");
|
|
17557
|
+
}
|
|
17558
|
+
erzeugt.push({
|
|
17559
|
+
imageBase64: antwort.base64,
|
|
17560
|
+
// Das tatsaechlich gerufene Modell, nicht der Flow-Display-Name —
|
|
17561
|
+
// im Bestand soll stehen, was bezahlt wurde (wie reactImageProvider.ts).
|
|
17562
|
+
model: input.callableModelId
|
|
17563
|
+
// Kein Seed: weder als Eingabe dokumentiert noch als Ausgabe
|
|
17564
|
+
// geliefert — nichts wird erfunden (D-107).
|
|
17565
|
+
});
|
|
17566
|
+
} catch (fehler4) {
|
|
17567
|
+
ersterFehler = fehler4 instanceof Error ? fehler4.message : String(fehler4);
|
|
17568
|
+
break;
|
|
17569
|
+
}
|
|
17570
|
+
}
|
|
17571
|
+
if (erzeugt.length === 0) {
|
|
17572
|
+
throw new Error(
|
|
17573
|
+
ersterFehler ?? `Flow.generate.image hat zu ${input.callableModelId} kein verwertbares Bild geliefert.`
|
|
17574
|
+
);
|
|
17575
|
+
}
|
|
17576
|
+
return { images: erzeugt };
|
|
17577
|
+
}
|
|
17578
|
+
};
|
|
17579
|
+
}
|
|
17580
|
+
|
|
17581
|
+
// src/lib/szenen/imageGenerationOrderStore.ts
|
|
17582
|
+
function istText2(wert) {
|
|
17583
|
+
return typeof wert === "string" && wert.trim().length > 0;
|
|
17584
|
+
}
|
|
17585
|
+
function collectImageGenerationOrders(events) {
|
|
17586
|
+
const byBatchId = /* @__PURE__ */ new Map();
|
|
17587
|
+
for (const event of events) {
|
|
17588
|
+
if (event.type !== SZENEN_EVENT_TYPES.imageGenerationStarted) continue;
|
|
17589
|
+
const payload = event.payload;
|
|
17590
|
+
if (!payload || !istText2(payload.generation_batch_id) || !istText2(payload.prompt_run_id)) continue;
|
|
17591
|
+
if (byBatchId.has(payload.generation_batch_id)) continue;
|
|
17592
|
+
byBatchId.set(payload.generation_batch_id, {
|
|
17593
|
+
generation_batch_id: payload.generation_batch_id,
|
|
17594
|
+
prompt_run_id: payload.prompt_run_id,
|
|
17595
|
+
source_kind: "generated_in_app",
|
|
17596
|
+
request: payload.request,
|
|
17597
|
+
created_at: payload.created_at ?? "",
|
|
17598
|
+
status: "started"
|
|
17599
|
+
});
|
|
17600
|
+
}
|
|
17601
|
+
for (const event of events) {
|
|
17602
|
+
if (event.type !== SZENEN_EVENT_TYPES.imageGenerationFinished) continue;
|
|
17603
|
+
const payload = event.payload;
|
|
17604
|
+
if (!payload || !istText2(payload.generation_batch_id)) continue;
|
|
17605
|
+
const auftrag = byBatchId.get(payload.generation_batch_id);
|
|
17606
|
+
if (!auftrag) continue;
|
|
17607
|
+
if (auftrag.status !== "started") continue;
|
|
17608
|
+
if (payload.status !== "succeeded" && payload.status !== "partial" && payload.status !== "failed") continue;
|
|
17609
|
+
byBatchId.set(payload.generation_batch_id, {
|
|
17610
|
+
...auftrag,
|
|
17611
|
+
status: payload.status,
|
|
17612
|
+
...payload.item_id ? { item_id: payload.item_id } : {},
|
|
17613
|
+
produced_count: payload.produced_count ?? 0,
|
|
17614
|
+
...payload.diagnostic ? { diagnostic: payload.diagnostic } : {},
|
|
17615
|
+
finished_at: payload.finished_at ?? ""
|
|
17616
|
+
});
|
|
17617
|
+
}
|
|
17618
|
+
return [...byBatchId.values()];
|
|
17619
|
+
}
|
|
17620
|
+
function ordersForPromptRun(events, runId) {
|
|
17621
|
+
return collectImageGenerationOrders(events).filter((o) => o.prompt_run_id === runId);
|
|
17622
|
+
}
|
|
17623
|
+
|
|
17624
|
+
// src/lib/szenen/imageBatchStore.ts
|
|
17625
|
+
var istText3 = (wert) => typeof wert === "string" && wert.trim().length > 0;
|
|
17626
|
+
function alsBilder(rohe) {
|
|
17627
|
+
if (!Array.isArray(rohe)) return [];
|
|
17628
|
+
return rohe.filter((b) => !!b && typeof b === "object").filter((b) => istText3(b.media_ref) && typeof b.position === "number").map((b) => ({
|
|
17629
|
+
media_ref: b.media_ref,
|
|
17630
|
+
position: b.position,
|
|
17631
|
+
...istText3(b.asset_id) ? { asset_id: b.asset_id } : {},
|
|
17632
|
+
model: b.model ?? null,
|
|
17633
|
+
seed: b.seed ?? null,
|
|
17634
|
+
width: b.width ?? null,
|
|
17635
|
+
height: b.height ?? null
|
|
17636
|
+
}));
|
|
17637
|
+
}
|
|
17638
|
+
function collectImageBatches(events) {
|
|
17639
|
+
const byItemId = /* @__PURE__ */ new Map();
|
|
17640
|
+
for (const event of events) {
|
|
17641
|
+
if (event.type !== SZENEN_EVENT_TYPES.imageBatchPersisted) continue;
|
|
17642
|
+
const payload = event.payload;
|
|
17643
|
+
if (!payload || !istText3(payload.item_id) || !istText3(payload.prompt_run_id) || !istText3(payload.generation_batch_id)) continue;
|
|
17644
|
+
if (payload.source_kind !== "generated_in_app" && payload.source_kind !== "external_import") continue;
|
|
17645
|
+
const bestehend = byItemId.get(payload.item_id);
|
|
17646
|
+
if (bestehend?.generation_batch_ids.includes(payload.generation_batch_id)) continue;
|
|
17647
|
+
const bilder = alsBilder(payload.images);
|
|
17648
|
+
if (!bestehend) {
|
|
17649
|
+
byItemId.set(payload.item_id, {
|
|
17650
|
+
item_id: payload.item_id,
|
|
17651
|
+
prompt_run_id: payload.prompt_run_id,
|
|
17652
|
+
generation_batch_ids: [payload.generation_batch_id],
|
|
17653
|
+
source_kind: payload.source_kind,
|
|
17654
|
+
title: istText3(payload.title) ? payload.title : `Batch aus Lauf ${payload.prompt_run_id}`,
|
|
17655
|
+
images: bilder
|
|
17656
|
+
});
|
|
17657
|
+
continue;
|
|
17658
|
+
}
|
|
17659
|
+
byItemId.set(payload.item_id, {
|
|
17660
|
+
...bestehend,
|
|
17661
|
+
generation_batch_ids: [...bestehend.generation_batch_ids, payload.generation_batch_id],
|
|
17662
|
+
images: [...bestehend.images, ...bilder]
|
|
17663
|
+
});
|
|
17664
|
+
}
|
|
17665
|
+
return [...byItemId.values()];
|
|
17666
|
+
}
|
|
17667
|
+
function batchesForPromptRun(events, runId) {
|
|
17668
|
+
return collectImageBatches(events).filter((b) => b.prompt_run_id === runId);
|
|
17669
|
+
}
|
|
17670
|
+
function findImageBatch(events, batchId) {
|
|
17671
|
+
return collectImageBatches(events).find((b) => b.generation_batch_ids.includes(batchId)) ?? null;
|
|
17672
|
+
}
|
|
17673
|
+
|
|
17674
|
+
// src/lib/szenen/hfImageBatchHistory.ts
|
|
17675
|
+
function lesefehler(aktion, error) {
|
|
17676
|
+
return {
|
|
17677
|
+
kind: "error",
|
|
17678
|
+
message: `${aktion}: ${error instanceof Error ? error.message : String(error)}`,
|
|
17679
|
+
retryable: true
|
|
17680
|
+
};
|
|
17681
|
+
}
|
|
17682
|
+
function createHfImageBatchHistory(options) {
|
|
17683
|
+
const { channel } = options;
|
|
17684
|
+
return {
|
|
17685
|
+
async listBatchesForPromptRun(runId) {
|
|
17686
|
+
try {
|
|
17687
|
+
const events = await channel.readEvents();
|
|
17688
|
+
return { kind: "ok", value: batchesForPromptRun(events, runId) };
|
|
17689
|
+
} catch (error) {
|
|
17690
|
+
return lesefehler(`Batches fuer Lauf ${runId} konnten nicht gelesen werden`, error);
|
|
17691
|
+
}
|
|
17692
|
+
},
|
|
17693
|
+
async getBatch(batchId) {
|
|
17694
|
+
try {
|
|
17695
|
+
const events = await channel.readEvents();
|
|
17696
|
+
return { kind: "ok", value: findImageBatch(events, batchId) };
|
|
17697
|
+
} catch (error) {
|
|
17698
|
+
return lesefehler(`Batch ${batchId} konnte nicht gelesen werden`, error);
|
|
17699
|
+
}
|
|
17700
|
+
},
|
|
17701
|
+
async listOrdersForPromptRun(runId) {
|
|
17702
|
+
try {
|
|
17703
|
+
const events = await channel.readEvents();
|
|
17704
|
+
return { kind: "ok", value: ordersForPromptRun(events, runId) };
|
|
17705
|
+
} catch (error) {
|
|
17706
|
+
return lesefehler(`Bildgenerierungsauftraege fuer Lauf ${runId} konnten nicht gelesen werden`, error);
|
|
17707
|
+
}
|
|
17708
|
+
}
|
|
17709
|
+
};
|
|
17710
|
+
}
|
|
17711
|
+
|
|
17712
|
+
// src/lib/szenen/hfImageBatchPersistence.ts
|
|
17713
|
+
init_hfStateService();
|
|
17714
|
+
init_hfEventLog();
|
|
17715
|
+
function fehler3(nachricht, retryable = true) {
|
|
17716
|
+
return { kind: "error", message: nachricht, retryable };
|
|
17717
|
+
}
|
|
17718
|
+
async function legeBatchAb(options, input) {
|
|
17719
|
+
const { namespace, token, channel } = options;
|
|
17720
|
+
const newImageId = options.newImageId ?? ((batchId, position) => `${batchId}-${position}`);
|
|
17721
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
17722
|
+
const itemId = itemIdForRun(input.runId);
|
|
17723
|
+
let vorhandeneEvents;
|
|
17724
|
+
try {
|
|
17725
|
+
vorhandeneEvents = await channel.readEvents();
|
|
17726
|
+
} catch (error) {
|
|
17727
|
+
return fehler3(
|
|
17728
|
+
`Bild-Batches von Lauf ${input.runId} konnten vor dem Ablegen nicht gelesen werden: ${error instanceof Error ? error.message : String(error)}`
|
|
17729
|
+
);
|
|
17730
|
+
}
|
|
17731
|
+
const bestehend = batchesForPromptRun(vorhandeneEvents, input.runId)[0] ?? null;
|
|
17732
|
+
if (bestehend?.generation_batch_ids.includes(input.generationBatchId)) {
|
|
17733
|
+
return { kind: "ok", value: bestehend };
|
|
17734
|
+
}
|
|
17735
|
+
const startPosition = bestehend?.images.length ?? 0;
|
|
17736
|
+
const abgelegt = [];
|
|
17737
|
+
for (let offset = 0; offset < input.images.length; offset++) {
|
|
17738
|
+
const bild = input.images[offset];
|
|
17739
|
+
const id = newImageId(input.generationBatchId, startPosition + offset);
|
|
17740
|
+
try {
|
|
17741
|
+
await hfUploadImage(bild.imageBase64, id, token, bild.mimeType);
|
|
17742
|
+
await writeHFEvent(namespace, token, "image_added", {
|
|
17743
|
+
id,
|
|
17744
|
+
prompt: input.title ?? `Batch ${input.generationBatchId}`,
|
|
17745
|
+
tags: [],
|
|
17746
|
+
timestamp: now().getTime(),
|
|
17747
|
+
mimeType: bild.mimeType
|
|
17748
|
+
}, []);
|
|
17749
|
+
} catch (error) {
|
|
17750
|
+
return fehler3(
|
|
17751
|
+
`Bild ${offset + 1}/${input.images.length} des Batches ${input.generationBatchId} konnte nicht im Bildbestand abgelegt werden: ${error instanceof Error ? error.message : String(error)}. Bereits abgelegte Bilder dieses Versuchs (${abgelegt.length}) bleiben im Bestand, geh\xF6ren aber zu keinem Batch, solange das Batch-Ereignis nicht geschrieben ist.`
|
|
17752
|
+
);
|
|
17753
|
+
}
|
|
17754
|
+
abgelegt.push({
|
|
17755
|
+
position: startPosition + offset,
|
|
17756
|
+
media_ref: id,
|
|
17757
|
+
asset_id: id,
|
|
17758
|
+
model: bild.model ?? null,
|
|
17759
|
+
seed: bild.seed ?? null,
|
|
17760
|
+
width: bild.width ?? null,
|
|
17761
|
+
height: bild.height ?? null
|
|
17762
|
+
});
|
|
17763
|
+
}
|
|
17764
|
+
const titel = bestehend?.title ?? (input.title?.trim() || `Batch aus Lauf ${input.runId}`);
|
|
17765
|
+
const payload = {
|
|
17766
|
+
item_id: itemId,
|
|
17767
|
+
prompt_run_id: input.runId,
|
|
17768
|
+
generation_batch_id: input.generationBatchId,
|
|
17769
|
+
source_kind: input.sourceKind,
|
|
17770
|
+
title: titel,
|
|
17771
|
+
images: abgelegt,
|
|
17772
|
+
created_at: now().toISOString()
|
|
17773
|
+
};
|
|
17774
|
+
try {
|
|
17775
|
+
await channel.appendEvent(SZENEN_EVENT_TYPES.imageBatchPersisted, payload);
|
|
17776
|
+
} catch (error) {
|
|
17777
|
+
return fehler3(
|
|
17778
|
+
`Die Batch-Metadaten fuer ${input.generationBatchId} konnten nicht protokolliert werden, obwohl die Bilder bereits im Bestand liegen: ${error instanceof Error ? error.message : String(error)}`
|
|
17779
|
+
);
|
|
17780
|
+
}
|
|
17781
|
+
const zusammengefuehrt = {
|
|
17782
|
+
item_id: itemId,
|
|
17783
|
+
prompt_run_id: input.runId,
|
|
17784
|
+
generation_batch_ids: bestehend ? [...bestehend.generation_batch_ids, input.generationBatchId] : [input.generationBatchId],
|
|
17785
|
+
source_kind: bestehend?.source_kind ?? input.sourceKind,
|
|
17786
|
+
title: titel,
|
|
17787
|
+
images: [...bestehend?.images ?? [], ...abgelegt]
|
|
17788
|
+
};
|
|
17789
|
+
return { kind: "ok", value: zusammengefuehrt };
|
|
17790
|
+
}
|
|
17791
|
+
function createHfImageGenerationBatchPersistence(options) {
|
|
17792
|
+
return {
|
|
17793
|
+
async persist(input) {
|
|
17794
|
+
return legeBatchAb(options, {
|
|
17795
|
+
runId: input.runId,
|
|
17796
|
+
generationBatchId: input.generationBatchId,
|
|
17797
|
+
sourceKind: "generated_in_app",
|
|
17798
|
+
images: input.images.map((bild) => ({
|
|
17799
|
+
imageBase64: bild.imageBase64,
|
|
17800
|
+
// Flow liefert PNG-Base64 (bestehende Konvention, s. AvatarArchitectApp.tsx
|
|
17801
|
+
// `data:image/png;base64,${base64}`); der gemeinsame Vertrag führt
|
|
17802
|
+
// keinen MIME-Typ je Bild.
|
|
17803
|
+
mimeType: "image/png",
|
|
17804
|
+
model: bild.model ?? null,
|
|
17805
|
+
seed: bild.seed ?? null,
|
|
17806
|
+
width: bild.width ?? null,
|
|
17807
|
+
height: bild.height ?? null
|
|
17808
|
+
}))
|
|
17809
|
+
});
|
|
17810
|
+
}
|
|
17811
|
+
};
|
|
17812
|
+
}
|
|
17813
|
+
function createHfImageBatchWrite(options) {
|
|
17814
|
+
return {
|
|
17815
|
+
async importBatch(input) {
|
|
17816
|
+
return legeBatchAb(options, {
|
|
17817
|
+
runId: input.runId,
|
|
17818
|
+
generationBatchId: input.generationBatchId,
|
|
17819
|
+
sourceKind: "external_import",
|
|
17820
|
+
title: input.title,
|
|
17821
|
+
images: input.images.map((bild) => ({
|
|
17822
|
+
imageBase64: bild.imageBase64,
|
|
17823
|
+
mimeType: "image/png",
|
|
17824
|
+
model: bild.model ?? null,
|
|
17825
|
+
seed: bild.seed ?? null,
|
|
17826
|
+
width: bild.width ?? null,
|
|
17827
|
+
height: bild.height ?? null
|
|
17828
|
+
}))
|
|
17829
|
+
});
|
|
17830
|
+
},
|
|
17831
|
+
async attachLibraryItem(input) {
|
|
17832
|
+
let events;
|
|
17833
|
+
try {
|
|
17834
|
+
events = await options.channel.readEvents();
|
|
17835
|
+
} catch (error) {
|
|
17836
|
+
return {
|
|
17837
|
+
kind: "error",
|
|
17838
|
+
message: `Batches konnten nicht gelesen werden: ${error instanceof Error ? error.message : String(error)}`,
|
|
17839
|
+
retryable: true
|
|
17840
|
+
};
|
|
17841
|
+
}
|
|
17842
|
+
const item = collectImageBatches(events).find((b) => b.item_id === input.itemId);
|
|
17843
|
+
if (!item) {
|
|
17844
|
+
return { kind: "error", message: `Item ${input.itemId} ist unbekannt.`, retryable: false };
|
|
17845
|
+
}
|
|
17846
|
+
if (item.prompt_run_id !== input.runId) {
|
|
17847
|
+
return {
|
|
17848
|
+
kind: "conflict",
|
|
17849
|
+
message: `Item ${input.itemId} geh\xF6rt bereits zu Lauf ${item.prompt_run_id}.`,
|
|
17850
|
+
existingPromptRunId: item.prompt_run_id
|
|
17851
|
+
};
|
|
17852
|
+
}
|
|
17853
|
+
return { kind: "ok", value: item };
|
|
17854
|
+
}
|
|
17855
|
+
};
|
|
17856
|
+
}
|
|
17857
|
+
|
|
17858
|
+
// src/lib/szenen/imageGenerationCapability.ts
|
|
17859
|
+
var isObject9 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
17860
|
+
var IMAGE_MODEL_CATALOGUE = {
|
|
17861
|
+
imagen_4: {
|
|
17862
|
+
callable_model_id: "imagen-4.0-generate-001",
|
|
17863
|
+
provider: "google",
|
|
17864
|
+
max_images: 4,
|
|
17865
|
+
aspect_ratios: ["1:1", "3:4", "4:3", "9:16", "16:9"],
|
|
17866
|
+
supports_seed: true
|
|
17867
|
+
},
|
|
17868
|
+
imagen_3: {
|
|
17869
|
+
callable_model_id: "imagen-3.0-generate-001",
|
|
17870
|
+
provider: "google",
|
|
17871
|
+
max_images: 4,
|
|
17872
|
+
aspect_ratios: ["1:1", "3:4", "4:3", "9:16", "16:9"],
|
|
17873
|
+
supports_seed: true
|
|
17874
|
+
}
|
|
17875
|
+
};
|
|
17876
|
+
function callableImageModelFor(targetModelKey) {
|
|
17877
|
+
return IMAGE_MODEL_CATALOGUE[targetModelKey] ?? null;
|
|
17878
|
+
}
|
|
17879
|
+
function targetModelKeyOf(targetModel) {
|
|
17880
|
+
if (!isObject9(targetModel)) return null;
|
|
17881
|
+
return typeof targetModel.key === "string" && targetModel.key.length > 0 ? targetModel.key : null;
|
|
17882
|
+
}
|
|
17883
|
+
function capabilityForTargetModel(targetModel, hasAccess) {
|
|
17884
|
+
const key = targetModelKeyOf(targetModel);
|
|
17885
|
+
if (!key) {
|
|
17886
|
+
return {
|
|
17887
|
+
kind: "unsupported",
|
|
17888
|
+
target_model_key: "(unbekannt)",
|
|
17889
|
+
reason: 'Der eingefrorene Lauf tr\xE4gt kein "target_model.key" \u2014 es gibt nichts zuzuordnen.'
|
|
17890
|
+
};
|
|
17891
|
+
}
|
|
17892
|
+
const modell = callableImageModelFor(key);
|
|
17893
|
+
if (!modell) {
|
|
17894
|
+
return {
|
|
17895
|
+
kind: "unsupported",
|
|
17896
|
+
target_model_key: key,
|
|
17897
|
+
reason: `F\xFCr das Zielmodell "${key}" ist in diesem Host kein Bildpfad katalogisiert.`
|
|
17898
|
+
};
|
|
17899
|
+
}
|
|
17900
|
+
if (!hasAccess(modell)) {
|
|
17901
|
+
return {
|
|
17902
|
+
kind: "unsupported",
|
|
17903
|
+
target_model_key: key,
|
|
17904
|
+
reason: `Dieser Host hat keinen Zugang zu ${modell.callable_model_id} (${modell.provider}).`
|
|
17905
|
+
};
|
|
17906
|
+
}
|
|
17907
|
+
return {
|
|
17908
|
+
kind: "supported",
|
|
17909
|
+
target_model_key: key,
|
|
17910
|
+
provider: modell.provider,
|
|
17911
|
+
callable_model_id: modell.callable_model_id,
|
|
17912
|
+
max_images: modell.max_images,
|
|
17913
|
+
aspect_ratios: modell.aspect_ratios,
|
|
17914
|
+
supports_seed: modell.supports_seed
|
|
17915
|
+
};
|
|
17916
|
+
}
|
|
17917
|
+
|
|
17918
|
+
// src/lib/szenen/imageGenerationPort.ts
|
|
17919
|
+
function queryError2(error, action) {
|
|
17920
|
+
return {
|
|
17921
|
+
kind: "error",
|
|
17922
|
+
message: `${action}: ${error instanceof Error ? error.message : String(error)}`,
|
|
17923
|
+
retryable: true
|
|
17924
|
+
};
|
|
17925
|
+
}
|
|
17926
|
+
function createImageGenerationPort(options) {
|
|
17927
|
+
const { runs, provider, batches, events, hasAccess } = options;
|
|
17928
|
+
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
17929
|
+
async function readRun(runId) {
|
|
17930
|
+
try {
|
|
17931
|
+
return await runs.getRun(runId);
|
|
17932
|
+
} catch (error) {
|
|
17933
|
+
return queryError2(error, `Lauf ${runId} konnte nicht gelesen werden`);
|
|
17934
|
+
}
|
|
17935
|
+
}
|
|
17936
|
+
return {
|
|
17937
|
+
async capabilityForRun(runId) {
|
|
17938
|
+
const gelesen = await readRun(runId);
|
|
17939
|
+
if (gelesen.kind !== "ok") return gelesen;
|
|
17940
|
+
if (!gelesen.value) {
|
|
17941
|
+
return { kind: "error", message: `Lauf ${runId} ist unbekannt.`, retryable: false };
|
|
17942
|
+
}
|
|
17943
|
+
const targetModel = gelesen.value.input_payload?.target_model;
|
|
17944
|
+
return { kind: "ok", value: capabilityForTargetModel(targetModel, hasAccess) };
|
|
17945
|
+
},
|
|
17946
|
+
async startFromPromptRun(input) {
|
|
17947
|
+
const gelesen = await readRun(input.runId);
|
|
17948
|
+
if (gelesen.kind !== "ok") return { kind: "rejected", message: gelesen.message };
|
|
17949
|
+
if (!gelesen.value) {
|
|
17950
|
+
return { kind: "rejected", message: `Lauf ${input.runId} ist unbekannt.` };
|
|
17951
|
+
}
|
|
17952
|
+
const run = gelesen.value;
|
|
17953
|
+
if (run.status !== "succeeded" || !run.output) {
|
|
17954
|
+
return {
|
|
17955
|
+
kind: "rejected",
|
|
17956
|
+
message: `Lauf ${input.runId} ist nicht erfolgreich \u2014 ein Bildauftrag braucht einen eingefrorenen Prompt (D-103).`
|
|
17957
|
+
};
|
|
17958
|
+
}
|
|
17959
|
+
const targetModel = run.input_payload?.target_model;
|
|
17960
|
+
const capability = capabilityForTargetModel(targetModel, hasAccess);
|
|
17961
|
+
if (capability.kind !== "supported") {
|
|
17962
|
+
return { kind: "unsupported", targetModelKey: capability.target_model_key, reason: capability.reason };
|
|
17963
|
+
}
|
|
17964
|
+
const startedPayload = {
|
|
17965
|
+
generation_batch_id: input.generationBatchId,
|
|
17966
|
+
prompt_run_id: input.runId,
|
|
17967
|
+
source_kind: "generated_in_app",
|
|
17968
|
+
request: {
|
|
17969
|
+
image_count: input.imageCount,
|
|
17970
|
+
...input.aspectRatio ? { aspect_ratio: input.aspectRatio } : {},
|
|
17971
|
+
...input.seeds ? { seeds: input.seeds } : {},
|
|
17972
|
+
callable_model_id: capability.callable_model_id
|
|
17973
|
+
},
|
|
17974
|
+
created_at: now().toISOString()
|
|
17975
|
+
};
|
|
17976
|
+
try {
|
|
17977
|
+
await events.appendEvent(SZENEN_EVENT_TYPES.imageGenerationStarted, startedPayload);
|
|
17978
|
+
} catch (error) {
|
|
17979
|
+
return {
|
|
17980
|
+
kind: "failed",
|
|
17981
|
+
message: `Der Auftrag ${input.generationBatchId} konnte nicht protokolliert werden: ${error instanceof Error ? error.message : String(error)}`
|
|
17982
|
+
};
|
|
17983
|
+
}
|
|
17984
|
+
let produced = [];
|
|
17985
|
+
let providerFehler = null;
|
|
17986
|
+
try {
|
|
17987
|
+
const antwort = await provider.generate({
|
|
17988
|
+
callableModelId: capability.callable_model_id,
|
|
17989
|
+
provider: capability.provider,
|
|
17990
|
+
positivePrompt: run.output.positive,
|
|
17991
|
+
negativePrompt: run.output.negative,
|
|
17992
|
+
imageCount: input.imageCount,
|
|
17993
|
+
...input.aspectRatio ? { aspectRatio: input.aspectRatio } : {},
|
|
17994
|
+
...input.seeds ? { seeds: input.seeds } : {}
|
|
17995
|
+
});
|
|
17996
|
+
produced = antwort.images;
|
|
17997
|
+
} catch (error) {
|
|
17998
|
+
providerFehler = error instanceof Error ? error.message : String(error);
|
|
17999
|
+
}
|
|
18000
|
+
if (providerFehler || produced.length === 0) {
|
|
18001
|
+
const finishedPayload2 = {
|
|
18002
|
+
generation_batch_id: input.generationBatchId,
|
|
18003
|
+
status: "failed",
|
|
18004
|
+
produced_count: 0,
|
|
18005
|
+
diagnostic: providerFehler ?? "Der Provider hat kein verwertbares Bild geliefert.",
|
|
18006
|
+
finished_at: now().toISOString()
|
|
18007
|
+
};
|
|
18008
|
+
await events.appendEvent(SZENEN_EVENT_TYPES.imageGenerationFinished, finishedPayload2).catch(() => {
|
|
18009
|
+
});
|
|
18010
|
+
return {
|
|
18011
|
+
kind: "failed",
|
|
18012
|
+
message: finishedPayload2.diagnostic
|
|
18013
|
+
};
|
|
18014
|
+
}
|
|
18015
|
+
const persistiert = await batches.persist({
|
|
18016
|
+
runId: input.runId,
|
|
18017
|
+
generationBatchId: input.generationBatchId,
|
|
18018
|
+
images: produced
|
|
18019
|
+
});
|
|
18020
|
+
if (persistiert.kind !== "ok") {
|
|
18021
|
+
const finishedPayload2 = {
|
|
18022
|
+
generation_batch_id: input.generationBatchId,
|
|
18023
|
+
status: "failed",
|
|
18024
|
+
produced_count: 0,
|
|
18025
|
+
diagnostic: persistiert.kind === "error" ? persistiert.message : `Batch ${input.generationBatchId} konnte nicht gespeichert werden (${persistiert.kind}).`,
|
|
18026
|
+
finished_at: now().toISOString()
|
|
18027
|
+
};
|
|
18028
|
+
await events.appendEvent(SZENEN_EVENT_TYPES.imageGenerationFinished, finishedPayload2).catch(() => {
|
|
18029
|
+
});
|
|
18030
|
+
return { kind: "failed", message: finishedPayload2.diagnostic };
|
|
18031
|
+
}
|
|
18032
|
+
const istPartial = produced.length < input.imageCount;
|
|
18033
|
+
const finishedPayload = {
|
|
18034
|
+
generation_batch_id: input.generationBatchId,
|
|
18035
|
+
status: istPartial ? "partial" : "succeeded",
|
|
18036
|
+
item_id: persistiert.value.item_id,
|
|
18037
|
+
produced_count: produced.length,
|
|
18038
|
+
finished_at: now().toISOString()
|
|
18039
|
+
};
|
|
18040
|
+
await events.appendEvent(SZENEN_EVENT_TYPES.imageGenerationFinished, finishedPayload).catch(() => {
|
|
18041
|
+
});
|
|
18042
|
+
return istPartial ? { kind: "partial", batch: persistiert.value, requested: input.imageCount, produced: produced.length } : { kind: "succeeded", batch: persistiert.value };
|
|
18043
|
+
}
|
|
18044
|
+
};
|
|
18045
|
+
}
|
|
18046
|
+
|
|
17467
18047
|
// src/lib/szenen/flowViewPort.ts
|
|
17468
18048
|
var defaultContext = {
|
|
17469
18049
|
async chainFor(contextId) {
|
|
@@ -17511,11 +18091,90 @@ function createFlowSzenenViewPort(options) {
|
|
|
17511
18091
|
...options.newRunId ? { newRunId: options.newRunId } : {},
|
|
17512
18092
|
...options.now ? { now: options.now } : {}
|
|
17513
18093
|
});
|
|
17514
|
-
const
|
|
18094
|
+
const imageBatchHistory = createHfImageBatchHistory({ channel });
|
|
18095
|
+
const hatHfZugangsdaten = Boolean(options.namespace?.trim() && options.token?.trim());
|
|
18096
|
+
const imageBatchWrite = hatHfZugangsdaten ? createHfImageBatchWrite({
|
|
18097
|
+
namespace: options.namespace,
|
|
18098
|
+
token: options.token,
|
|
18099
|
+
channel,
|
|
18100
|
+
...options.newBatchImageId ? { newImageId: options.newBatchImageId } : {},
|
|
18101
|
+
...options.now ? { now: options.now } : {}
|
|
18102
|
+
}) : void 0;
|
|
18103
|
+
const bildProvider = options.imageProvider ?? (options.generateImage ? createFlowImageProvider(options.generateImage) : void 0);
|
|
18104
|
+
const imageGeneration = bildProvider && imageBatchWrite ? createImageGenerationPort({
|
|
18105
|
+
runs: { async getRun(runId) {
|
|
18106
|
+
return runs.getRun(runId);
|
|
18107
|
+
} },
|
|
18108
|
+
provider: bildProvider,
|
|
18109
|
+
batches: createHfImageGenerationBatchPersistence({
|
|
18110
|
+
namespace: options.namespace,
|
|
18111
|
+
token: options.token,
|
|
18112
|
+
channel,
|
|
18113
|
+
...options.newBatchImageId ? { newImageId: options.newBatchImageId } : {},
|
|
18114
|
+
...options.now ? { now: options.now } : {}
|
|
18115
|
+
}),
|
|
18116
|
+
events: channel,
|
|
18117
|
+
hasAccess: options.imageProviderHasAccess ?? flowImageProviderHasAccess,
|
|
18118
|
+
...options.now ? { now: options.now } : {}
|
|
18119
|
+
}) : void 0;
|
|
18120
|
+
const port = { elements, context, runs, derivation, imageBatchHistory };
|
|
17515
18121
|
if (imageLibrary) port.imageLibrary = imageLibrary;
|
|
18122
|
+
if (imageBatchWrite) port.imageBatchWrite = imageBatchWrite;
|
|
18123
|
+
if (imageGeneration) port.imageGeneration = imageGeneration;
|
|
17516
18124
|
return port;
|
|
17517
18125
|
}
|
|
17518
18126
|
|
|
18127
|
+
// src/lib/flowBootstrapTarget.ts
|
|
18128
|
+
var PROD_NAMESPACE = "app.art-by-rolands.de/";
|
|
18129
|
+
var DEV_NAMESPACE = "dev-app.art-by-rolands.de/";
|
|
18130
|
+
var SELECTABLE_NAMESPACES = [PROD_NAMESPACE, DEV_NAMESPACE];
|
|
18131
|
+
var DEFAULT_NAMESPACE = PROD_NAMESPACE;
|
|
18132
|
+
function environmentForNamespace(namespace) {
|
|
18133
|
+
if (!namespace) return null;
|
|
18134
|
+
if (namespace === DEV_NAMESPACE) return "dev";
|
|
18135
|
+
if (namespace === PROD_NAMESPACE) return "prod";
|
|
18136
|
+
return null;
|
|
18137
|
+
}
|
|
18138
|
+
function normalizeSelectableNamespace(namespace) {
|
|
18139
|
+
return namespace && SELECTABLE_NAMESPACES.includes(namespace) ? namespace : DEFAULT_NAMESPACE;
|
|
18140
|
+
}
|
|
18141
|
+
function resolveBootstrapTarget(input) {
|
|
18142
|
+
const { hostNamespace, serverNamespace, isProbingServer = false } = input;
|
|
18143
|
+
if (hostNamespace) {
|
|
18144
|
+
return {
|
|
18145
|
+
source: "host",
|
|
18146
|
+
phase: "ready",
|
|
18147
|
+
ready: true,
|
|
18148
|
+
namespace: hostNamespace,
|
|
18149
|
+
environment: environmentForNamespace(hostNamespace)
|
|
18150
|
+
};
|
|
18151
|
+
}
|
|
18152
|
+
if (serverNamespace) {
|
|
18153
|
+
return {
|
|
18154
|
+
source: "server",
|
|
18155
|
+
phase: "ready",
|
|
18156
|
+
ready: true,
|
|
18157
|
+
namespace: serverNamespace,
|
|
18158
|
+
environment: environmentForNamespace(serverNamespace)
|
|
18159
|
+
};
|
|
18160
|
+
}
|
|
18161
|
+
if (isProbingServer) {
|
|
18162
|
+
return { source: "server", phase: "probing", ready: false, namespace: null, environment: null };
|
|
18163
|
+
}
|
|
18164
|
+
const { selectedNamespace, isStartDialogOpen = false } = input;
|
|
18165
|
+
if (isStartDialogOpen) {
|
|
18166
|
+
return { source: "dialog", phase: "awaiting-choice", ready: false, namespace: null, environment: null };
|
|
18167
|
+
}
|
|
18168
|
+
const namespace = normalizeSelectableNamespace(selectedNamespace);
|
|
18169
|
+
return {
|
|
18170
|
+
source: "dialog",
|
|
18171
|
+
phase: "ready",
|
|
18172
|
+
ready: true,
|
|
18173
|
+
namespace,
|
|
18174
|
+
environment: environmentForNamespace(namespace)
|
|
18175
|
+
};
|
|
18176
|
+
}
|
|
18177
|
+
|
|
17519
18178
|
// src/components/AvatarArchitectApp.tsx
|
|
17520
18179
|
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
17521
18180
|
function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onSelectMedia, buildInfo, initialHfToken, hfNamespace, allowDevNamespace, requireWorkspaceSelection = false, serverBaseUrl, onFetchServerProjects, onServerSave, onServerLoad, onServerDelete }) {
|
|
@@ -17542,31 +18201,38 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
17542
18201
|
const [hfTokenInput, setHfTokenInput] = (0, import_react47.useState)(initialHfToken || "");
|
|
17543
18202
|
const [isLoadingFromHF, setIsLoadingFromHF] = (0, import_react47.useState)(false);
|
|
17544
18203
|
const [hfNamespaceLocal, setHfNamespaceLocal] = (0, import_react47.useState)(() => {
|
|
17545
|
-
const KNOWN = ["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"];
|
|
17546
|
-
const DEFAULT = "app.art-by-rolands.de/";
|
|
17547
18204
|
try {
|
|
17548
|
-
|
|
17549
|
-
if (stored && KNOWN.includes(stored)) return stored;
|
|
17550
|
-
localStorage.setItem("aa-hf-namespace", DEFAULT);
|
|
17551
|
-
return DEFAULT;
|
|
18205
|
+
return normalizeSelectableNamespace(localStorage.getItem("aa-hf-namespace"));
|
|
17552
18206
|
} catch {
|
|
17553
|
-
return
|
|
18207
|
+
return DEFAULT_NAMESPACE;
|
|
17554
18208
|
}
|
|
17555
18209
|
});
|
|
17556
18210
|
const [hfNamespaceFromServer, setHfNamespaceFromServer] = (0, import_react47.useState)(null);
|
|
18211
|
+
const [serverProbeFailed, setServerProbeFailed] = (0, import_react47.useState)(false);
|
|
17557
18212
|
(0, import_react47.useEffect)(() => {
|
|
17558
18213
|
if (hfNamespace !== void 0 || !serverBaseUrl) return;
|
|
17559
18214
|
fetch(`${serverBaseUrl}/api/status`).then((r) => r.json()).then((d) => {
|
|
17560
18215
|
if (typeof d.hfNamespace === "string" && d.hfNamespace) setHfNamespaceFromServer(d.hfNamespace);
|
|
17561
|
-
|
|
17562
|
-
});
|
|
18216
|
+
else setServerProbeFailed(true);
|
|
18217
|
+
}).catch(() => setServerProbeFailed(true));
|
|
17563
18218
|
}, [hfNamespace, serverBaseUrl]);
|
|
17564
|
-
const
|
|
17565
|
-
const
|
|
18219
|
+
const [targetConfirmed, setTargetConfirmed] = (0, import_react47.useState)(false);
|
|
18220
|
+
const isDialogTarget = hfNamespace === void 0 && hfNamespaceFromServer === null && (!serverBaseUrl || serverProbeFailed);
|
|
18221
|
+
const isProbingServer = hfNamespace === void 0 && !!serverBaseUrl && hfNamespaceFromServer === null && !serverProbeFailed;
|
|
18222
|
+
const bootstrapTarget = resolveBootstrapTarget({
|
|
18223
|
+
hostNamespace: hfNamespace,
|
|
18224
|
+
serverNamespace: hfNamespaceFromServer,
|
|
18225
|
+
isProbingServer,
|
|
18226
|
+
selectedNamespace: hfNamespaceLocal,
|
|
18227
|
+
isStartDialogOpen: isDialogTarget && !targetConfirmed
|
|
18228
|
+
});
|
|
18229
|
+
const effectiveNamespace = bootstrapTarget.namespace ?? "";
|
|
18230
|
+
const szenenPort = (0, import_react47.useMemo)(() => hfToken && effectiveNamespace ? createFlowSzenenViewPort({
|
|
17566
18231
|
generateText: onGeneratePrompt,
|
|
17567
18232
|
token: hfToken,
|
|
17568
|
-
namespace: effectiveNamespace
|
|
17569
|
-
|
|
18233
|
+
namespace: effectiveNamespace,
|
|
18234
|
+
generateImage: onGenerateImage
|
|
18235
|
+
}) : null, [hfToken, effectiveNamespace, onGeneratePrompt, onGenerateImage]);
|
|
17570
18236
|
const {
|
|
17571
18237
|
state: hfState,
|
|
17572
18238
|
isLoading: isHfRefreshing,
|
|
@@ -17640,6 +18306,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
17640
18306
|
} catch {
|
|
17641
18307
|
}
|
|
17642
18308
|
setLayoutChoice(choice);
|
|
18309
|
+
setTargetConfirmed(true);
|
|
17643
18310
|
setShowStart(false);
|
|
17644
18311
|
};
|
|
17645
18312
|
const [nodes, setNodes] = (0, import_react47.useState)([{ id: "1", type: "custom", position: { x: 0, y: 0 }, data: { label: "Fine Art Project", placeholder: "Name..." } }]);
|
|
@@ -18401,45 +19068,6 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
18401
19068
|
const all = Object.entries(merged).flatMap(([cat, tags]) => tags.map((t) => ({ ...t, category: cat })));
|
|
18402
19069
|
return { by_category: merged, all };
|
|
18403
19070
|
};
|
|
18404
|
-
if (requireWorkspaceSelection) {
|
|
18405
|
-
if (!hfToken) {
|
|
18406
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("section", { className: "flow-workspace-picker__card", role: "alert", children: "HF-Token fehlt \u2014 User und Context koennen nicht aus der Tag-Base geladen werden." }) });
|
|
18407
|
-
}
|
|
18408
|
-
if (tagBaseResult.isLoading) {
|
|
18409
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: "flow-workspace-picker__card", children: [
|
|
18410
|
-
"Lade User und Contexts aus ",
|
|
18411
|
-
effectiveNamespace,
|
|
18412
|
-
"\u2026"
|
|
18413
|
-
] }) });
|
|
18414
|
-
}
|
|
18415
|
-
if (tagBaseResult.error) {
|
|
18416
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: "flow-workspace-picker__card", role: "alert", children: [
|
|
18417
|
-
"Tag-Base ",
|
|
18418
|
-
effectiveNamespace,
|
|
18419
|
-
" konnte nicht geladen werden: ",
|
|
18420
|
-
tagBaseResult.error
|
|
18421
|
-
] }) });
|
|
18422
|
-
}
|
|
18423
|
-
if (!tagBaseResult.tagBase) {
|
|
18424
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: "flow-workspace-picker__card", role: "alert", children: [
|
|
18425
|
-
"Im Namespace ",
|
|
18426
|
-
effectiveNamespace,
|
|
18427
|
-
" fehlt tags-state-*.zip. Der Server muss zuerst die Tag-Base erzeugen."
|
|
18428
|
-
] }) });
|
|
18429
|
-
}
|
|
18430
|
-
if (tagBaseResult.needsPicker) {
|
|
18431
|
-
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
18432
|
-
FlowWorkspacePicker,
|
|
18433
|
-
{
|
|
18434
|
-
tagBase: tagBaseResult.tagBase,
|
|
18435
|
-
selectedUserId: tagBaseResult.selectedUserId,
|
|
18436
|
-
message: tagBaseResult.pickerMessage,
|
|
18437
|
-
onSelectUser: tagBaseResult.selectUser,
|
|
18438
|
-
onSelectContext: tagBaseResult.selectContext
|
|
18439
|
-
}
|
|
18440
|
-
);
|
|
18441
|
-
}
|
|
18442
|
-
}
|
|
18443
19071
|
if (isFullscreen && currentResult?.base64) {
|
|
18444
19072
|
const fsRaw = currentResult.fullBase64 || currentResult.base64;
|
|
18445
19073
|
const fsBase64 = fsRaw.startsWith("data:") ? fsRaw : `data:image/png;base64,${fsRaw}`;
|
|
@@ -18583,7 +19211,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
18583
19211
|
}
|
|
18584
19212
|
)
|
|
18585
19213
|
] }),
|
|
18586
|
-
|
|
19214
|
+
isDialogTarget && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-3 w-full", children: [
|
|
18587
19215
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "text-white/25 text-[10px] uppercase tracking-widest font-bold flex-shrink-0", children: "State:" }),
|
|
18588
19216
|
["app.art-by-rolands.de/", "dev-app.art-by-rolands.de/"].map((ns, i) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
18589
19217
|
"button",
|
|
@@ -18668,7 +19296,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
18668
19296
|
"button",
|
|
18669
19297
|
{
|
|
18670
19298
|
type: "button",
|
|
18671
|
-
disabled: !szenenPort,
|
|
19299
|
+
disabled: !szenenPort || !bootstrapTarget.ready,
|
|
18672
19300
|
onClick: () => setShowSzenen(true),
|
|
18673
19301
|
children: [
|
|
18674
19302
|
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "material-symbols-outlined", children: "movie" }),
|
|
@@ -18703,6 +19331,48 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
|
|
|
18703
19331
|
] })
|
|
18704
19332
|
] });
|
|
18705
19333
|
}
|
|
19334
|
+
if (requireWorkspaceSelection) {
|
|
19335
|
+
if (!bootstrapTarget.ready) {
|
|
19336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("section", { className: "flow-workspace-picker__card", children: "Zielraum wird bestimmt\u2026" }) });
|
|
19337
|
+
}
|
|
19338
|
+
if (!hfToken) {
|
|
19339
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("section", { className: "flow-workspace-picker__card", role: "alert", children: "HF-Token fehlt \u2014 User und Context koennen nicht aus der Tag-Base geladen werden." }) });
|
|
19340
|
+
}
|
|
19341
|
+
if (tagBaseResult.isLoading) {
|
|
19342
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: "flow-workspace-picker__card", children: [
|
|
19343
|
+
"Lade User und Contexts aus ",
|
|
19344
|
+
effectiveNamespace,
|
|
19345
|
+
"\u2026"
|
|
19346
|
+
] }) });
|
|
19347
|
+
}
|
|
19348
|
+
if (tagBaseResult.error) {
|
|
19349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: "flow-workspace-picker__card", role: "alert", children: [
|
|
19350
|
+
"Tag-Base ",
|
|
19351
|
+
effectiveNamespace,
|
|
19352
|
+
" konnte nicht geladen werden: ",
|
|
19353
|
+
tagBaseResult.error
|
|
19354
|
+
] }) });
|
|
19355
|
+
}
|
|
19356
|
+
if (!tagBaseResult.tagBase) {
|
|
19357
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("main", { className: "flow-workspace-picker", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("section", { className: "flow-workspace-picker__card", role: "alert", children: [
|
|
19358
|
+
"Im Namespace ",
|
|
19359
|
+
effectiveNamespace,
|
|
19360
|
+
" fehlt tags-state-*.zip. Der Server muss zuerst die Tag-Base erzeugen."
|
|
19361
|
+
] }) });
|
|
19362
|
+
}
|
|
19363
|
+
if (tagBaseResult.needsPicker) {
|
|
19364
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
19365
|
+
FlowWorkspacePicker,
|
|
19366
|
+
{
|
|
19367
|
+
tagBase: tagBaseResult.tagBase,
|
|
19368
|
+
selectedUserId: tagBaseResult.selectedUserId,
|
|
19369
|
+
message: tagBaseResult.pickerMessage,
|
|
19370
|
+
onSelectUser: tagBaseResult.selectUser,
|
|
19371
|
+
onSelectContext: tagBaseResult.selectContext
|
|
19372
|
+
}
|
|
19373
|
+
);
|
|
19374
|
+
}
|
|
19375
|
+
}
|
|
18706
19376
|
if (layoutChoice === "mobile" || layoutChoice === "mobile-desktop") {
|
|
18707
19377
|
const mdMode = layoutChoice === "mobile-desktop";
|
|
18708
19378
|
const mdScale = mdMode ? window.innerWidth / 430 : 1;
|