@rslsp1/fa-app-tools 2.0.84 → 2.0.86
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-4FOEFCKM.mjs → chunk-DGFMONWO.mjs} +227 -56
- package/dist/{chunk-VBWQP7PO.mjs → chunk-LFPOXNOZ.mjs} +18 -3
- package/dist/hfEventTypes-C_PX6RFR.d.ts +241 -0
- package/dist/hfEventTypes-Dkfrcd_t.d.mts +241 -0
- package/dist/{hfStateService-WKQLNDHO.mjs → hfStateService-PZH2IDKF.mjs} +1 -1
- package/dist/index.d.mts +4 -172
- package/dist/index.d.ts +4 -172
- package/dist/index.js +176 -65
- package/dist/index.mjs +6 -74
- package/dist/szenen.d.mts +99 -5
- package/dist/szenen.d.ts +99 -5
- package/dist/szenen.js +248 -60
- package/dist/szenen.mjs +8 -2
- package/package.json +1 -1
- package/dist/flowTextGenerationPort-CeDUFutP.d.mts +0 -73
- package/dist/flowTextGenerationPort-KHjCGt_S.d.ts +0 -73
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
loadHFState,
|
|
11
11
|
loadPendingEvents,
|
|
12
12
|
writeHFEvent
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-LFPOXNOZ.mjs";
|
|
14
14
|
|
|
15
15
|
// src/lib/szenen/viewPort.ts
|
|
16
16
|
function capabilitiesOf(port) {
|
|
@@ -6468,8 +6468,8 @@ var BestandsBild = ({ port, mediaRef }) => {
|
|
|
6468
6468
|
};
|
|
6469
6469
|
var BatchBild = ({ port, bild }) => {
|
|
6470
6470
|
const [phase] = usePortQuery(
|
|
6471
|
-
() => port.imageLibrary ? port.imageLibrary.resolveImage(bild.media_ref) : Promise.resolve({ kind: "ok", value: null }),
|
|
6472
|
-
[port, bild.media_ref]
|
|
6471
|
+
() => port.imageLibrary ? port.imageLibrary.resolveImage(bild.media_ref, bild.mime_type ?? null) : Promise.resolve({ kind: "ok", value: null }),
|
|
6472
|
+
[port, bild.media_ref, bild.mime_type]
|
|
6473
6473
|
);
|
|
6474
6474
|
return /* @__PURE__ */ jsxs5("li", { "data-testid": `batchbild-${bild.media_ref}`, children: [
|
|
6475
6475
|
phase.status === "ready" && phase.value && /* @__PURE__ */ jsx5(
|
|
@@ -11067,6 +11067,179 @@ function createClientRunPort(options) {
|
|
|
11067
11067
|
};
|
|
11068
11068
|
}
|
|
11069
11069
|
|
|
11070
|
+
// src/lib/hfReducer.ts
|
|
11071
|
+
function applyEvent(state, event) {
|
|
11072
|
+
if (event.v.major > 1) return state;
|
|
11073
|
+
switch (event.type) {
|
|
11074
|
+
// SPEZ: image_added (state/spez/hf-state.spez.yaml)
|
|
11075
|
+
case "image_added": {
|
|
11076
|
+
const p = event.payload;
|
|
11077
|
+
if (state.metadata.some((m) => m.id === p.id)) return state;
|
|
11078
|
+
return { ...state, metadata: [...state.metadata, p] };
|
|
11079
|
+
}
|
|
11080
|
+
// SPEZ: task_requested (global/spez/task-queue.spez.yaml)
|
|
11081
|
+
case "task_requested": {
|
|
11082
|
+
const p = event.payload;
|
|
11083
|
+
if (p.expiresAt && p.expiresAt < event.ts) return state;
|
|
11084
|
+
const openTasks = { ...state.openTasks || {} };
|
|
11085
|
+
openTasks[p.taskId] = p;
|
|
11086
|
+
return { ...state, openTasks };
|
|
11087
|
+
}
|
|
11088
|
+
// SPEZ: task_completed (global/spez/task-queue.spez.yaml)
|
|
11089
|
+
case "task_completed": {
|
|
11090
|
+
const p = event.payload;
|
|
11091
|
+
if (!state.openTasks || !state.openTasks[p.taskId]) return state;
|
|
11092
|
+
const openTasks = { ...state.openTasks };
|
|
11093
|
+
delete openTasks[p.taskId];
|
|
11094
|
+
return { ...state, openTasks };
|
|
11095
|
+
}
|
|
11096
|
+
// SPEZ: tag_upserted (state/spez/hf-state.spez.yaml) — Legacy, wird nicht mehr erzeugt
|
|
11097
|
+
case "tag_upserted": {
|
|
11098
|
+
const p = event.payload;
|
|
11099
|
+
const tags = state.tags;
|
|
11100
|
+
const cat = tags.by_category[p.category] || [];
|
|
11101
|
+
const existing = cat.find((t) => t.value === p.value);
|
|
11102
|
+
const updated = { label: p.label, value: p.value, is_user_created: p.is_user_created, is_deleted: p.is_deleted };
|
|
11103
|
+
const newCat = existing ? cat.map((t) => t.value === p.value ? { ...t, ...updated } : t) : [...cat, updated];
|
|
11104
|
+
const newAll = tags.all.some((t) => t.value === p.value && t.category === p.category) ? tags.all.map((t) => t.value === p.value && t.category === p.category ? { ...t, ...updated, category: p.category } : t) : [...tags.all, { ...updated, category: p.category }];
|
|
11105
|
+
return { ...state, tags: { by_category: { ...tags.by_category, [p.category]: newCat }, all: newAll } };
|
|
11106
|
+
}
|
|
11107
|
+
// SPEZ: thumb_added (state/spez/hf-state.spez.yaml)
|
|
11108
|
+
case "thumb_added": {
|
|
11109
|
+
const p = event.payload;
|
|
11110
|
+
return {
|
|
11111
|
+
...state,
|
|
11112
|
+
metadata: state.metadata.map((m) => m.id === p.id ? { ...m, hasThumb: true } : m)
|
|
11113
|
+
};
|
|
11114
|
+
}
|
|
11115
|
+
// SPEZ: metadata_updated (state/spez/hf-state.spez.yaml)
|
|
11116
|
+
case "metadata_updated": {
|
|
11117
|
+
const p = event.payload;
|
|
11118
|
+
return {
|
|
11119
|
+
...state,
|
|
11120
|
+
metadata: state.metadata.map((m) => m.id === p.id ? { ...m, ...p.delta } : m)
|
|
11121
|
+
};
|
|
11122
|
+
}
|
|
11123
|
+
// SPEZ: title_set (state/spez/hf-state.spez.yaml)
|
|
11124
|
+
case "title_set": {
|
|
11125
|
+
const p = event.payload;
|
|
11126
|
+
return {
|
|
11127
|
+
...state,
|
|
11128
|
+
metadata: state.metadata.map((m) => m.id === p.id ? { ...m, titleTs: event.ts } : m)
|
|
11129
|
+
};
|
|
11130
|
+
}
|
|
11131
|
+
default:
|
|
11132
|
+
return state;
|
|
11133
|
+
}
|
|
11134
|
+
}
|
|
11135
|
+
function applyEvents(state, events) {
|
|
11136
|
+
return events.reduce(applyEvent, state);
|
|
11137
|
+
}
|
|
11138
|
+
|
|
11139
|
+
// src/lib/szenen/hfImageStore.ts
|
|
11140
|
+
var LEERER_BESTAND = {
|
|
11141
|
+
metadata: [],
|
|
11142
|
+
tags: { by_category: {}, all: [] },
|
|
11143
|
+
meta: { consolidatedAt: 0, version: 1 }
|
|
11144
|
+
};
|
|
11145
|
+
function endungFuer(mimeType) {
|
|
11146
|
+
return mimeType === "image/png" ? "png" : "jpg";
|
|
11147
|
+
}
|
|
11148
|
+
function bildPfad(id, mimeType) {
|
|
11149
|
+
return `images/${id}.${endungFuer(mimeType)}`;
|
|
11150
|
+
}
|
|
11151
|
+
function typAusBytes(base64, vorgabe = "image/png") {
|
|
11152
|
+
const kopf = base64.slice(0, 16);
|
|
11153
|
+
if (kopf.startsWith("iVBORw0KGgo")) return "image/png";
|
|
11154
|
+
if (kopf.startsWith("/9j/")) return "image/jpeg";
|
|
11155
|
+
if (kopf.startsWith("UklGR")) return "image/webp";
|
|
11156
|
+
if (kopf.startsWith("R0lGOD")) return "image/gif";
|
|
11157
|
+
return vorgabe;
|
|
11158
|
+
}
|
|
11159
|
+
var warten = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
11160
|
+
function createHfImageStore(options) {
|
|
11161
|
+
const { namespace, token } = options;
|
|
11162
|
+
const now = options.now ?? (() => Date.now());
|
|
11163
|
+
const versuche = options.leseVersuche ?? 4;
|
|
11164
|
+
const basisMs = options.leseBasisMs ?? 400;
|
|
11165
|
+
const schlafen = options.schlafen ?? warten;
|
|
11166
|
+
const abgelegt = /* @__PURE__ */ new Map();
|
|
11167
|
+
const bekanntePfade = /* @__PURE__ */ new Set();
|
|
11168
|
+
let gefalteterBestand = null;
|
|
11169
|
+
let laufenderAbgleich = null;
|
|
11170
|
+
async function bestandLesen() {
|
|
11171
|
+
const grundlage = gefalteterBestand ?? await loadHFState(namespace, token) ?? LEERER_BESTAND;
|
|
11172
|
+
const neue = await loadPendingEvents(
|
|
11173
|
+
namespace,
|
|
11174
|
+
token,
|
|
11175
|
+
grundlage.meta.consolidatedAt,
|
|
11176
|
+
bekanntePfade
|
|
11177
|
+
);
|
|
11178
|
+
const danach = neue.filter((e) => e.ts > grundlage.meta.consolidatedAt);
|
|
11179
|
+
gefalteterBestand = danach.length ? applyEvents(grundlage, danach) : grundlage;
|
|
11180
|
+
return gefalteterBestand;
|
|
11181
|
+
}
|
|
11182
|
+
function bestandAbgleichen() {
|
|
11183
|
+
if (!laufenderAbgleich) {
|
|
11184
|
+
laufenderAbgleich = bestandLesen().finally(() => {
|
|
11185
|
+
laufenderAbgleich = null;
|
|
11186
|
+
});
|
|
11187
|
+
}
|
|
11188
|
+
return laufenderAbgleich;
|
|
11189
|
+
}
|
|
11190
|
+
return {
|
|
11191
|
+
bestand: bestandAbgleichen,
|
|
11192
|
+
async putWithId(id, base64, mimeType, titel) {
|
|
11193
|
+
const echterTyp = typAusBytes(base64, mimeType);
|
|
11194
|
+
await hfUploadImage(base64, id, token, echterTyp);
|
|
11195
|
+
await writeHFEvent(namespace, token, "image_added", {
|
|
11196
|
+
id,
|
|
11197
|
+
prompt: titel ?? id,
|
|
11198
|
+
tags: [],
|
|
11199
|
+
timestamp: now(),
|
|
11200
|
+
mimeType: echterTyp
|
|
11201
|
+
}, []);
|
|
11202
|
+
abgelegt.set(id, { data: base64, mimeType: echterTyp });
|
|
11203
|
+
},
|
|
11204
|
+
async resolve(id, mimeType) {
|
|
11205
|
+
const eben = abgelegt.get(id);
|
|
11206
|
+
if (eben) return eben;
|
|
11207
|
+
const zustand = await bestandAbgleichen();
|
|
11208
|
+
const eintrag = zustand.metadata.find((e) => e.id === id);
|
|
11209
|
+
const typ = eintrag?.mimeType || mimeType || null;
|
|
11210
|
+
if (eintrag) {
|
|
11211
|
+
const base64 = await hfLoadImageAsBase64(
|
|
11212
|
+
id,
|
|
11213
|
+
token,
|
|
11214
|
+
void 0,
|
|
11215
|
+
eintrag.filename,
|
|
11216
|
+
void 0,
|
|
11217
|
+
eintrag.mimeType,
|
|
11218
|
+
false
|
|
11219
|
+
);
|
|
11220
|
+
if (base64) return { data: base64, mimeType: eintrag.mimeType || "image/jpeg" };
|
|
11221
|
+
}
|
|
11222
|
+
const pfadTyp = typ ?? "image/png";
|
|
11223
|
+
for (let versuch = 0; versuch < versuche; versuch += 1) {
|
|
11224
|
+
if (versuch > 0) await schlafen(basisMs * 2 ** (versuch - 1));
|
|
11225
|
+
const base64 = await hfLoadImageAsBase64(
|
|
11226
|
+
id,
|
|
11227
|
+
token,
|
|
11228
|
+
void 0,
|
|
11229
|
+
void 0,
|
|
11230
|
+
void 0,
|
|
11231
|
+
pfadTyp,
|
|
11232
|
+
false
|
|
11233
|
+
);
|
|
11234
|
+
if (base64) return { data: base64, mimeType: pfadTyp };
|
|
11235
|
+
}
|
|
11236
|
+
throw new Error(
|
|
11237
|
+
`Das Bild ${id} ist auf HF nicht auffindbar. Geprueft: ${bildPfad(id, pfadTyp)} in ${versuche} Versuchen` + (eintrag ? " (im Bestand verzeichnet, aber nicht ladbar)." : " (nicht im Bestand verzeichnet).")
|
|
11238
|
+
);
|
|
11239
|
+
}
|
|
11240
|
+
};
|
|
11241
|
+
}
|
|
11242
|
+
|
|
11070
11243
|
// src/lib/szenen/hfImageLibrary.ts
|
|
11071
11244
|
function fehler2(nachricht, retryable = false) {
|
|
11072
11245
|
return { kind: "error", message: nachricht, retryable };
|
|
@@ -11082,14 +11255,16 @@ function alsBild(eintrag) {
|
|
|
11082
11255
|
};
|
|
11083
11256
|
}
|
|
11084
11257
|
function createHfImageLibrary(options) {
|
|
11085
|
-
const { namespace, token } = options;
|
|
11086
11258
|
const newImageId = options.newImageId ?? (() => crypto.randomUUID());
|
|
11087
|
-
const
|
|
11088
|
-
|
|
11259
|
+
const store = options.store ?? createHfImageStore({
|
|
11260
|
+
namespace: options.namespace,
|
|
11261
|
+
token: options.token,
|
|
11262
|
+
...options.now ? { now: options.now } : {}
|
|
11263
|
+
});
|
|
11089
11264
|
return {
|
|
11090
11265
|
async listImages(query) {
|
|
11091
11266
|
try {
|
|
11092
|
-
const zustand = await
|
|
11267
|
+
const zustand = await store.bestand();
|
|
11093
11268
|
const eintraege = zustand?.metadata ?? [];
|
|
11094
11269
|
const gesucht = query?.search?.trim().toLowerCase();
|
|
11095
11270
|
const gefiltert = gesucht ? eintraege.filter((e) => (e.prompt ?? "").toLowerCase().includes(gesucht) || e.id.toLowerCase().includes(gesucht)) : eintraege;
|
|
@@ -11103,50 +11278,18 @@ function createHfImageLibrary(options) {
|
|
|
11103
11278
|
);
|
|
11104
11279
|
}
|
|
11105
11280
|
},
|
|
11106
|
-
async resolveImage(mediaRef) {
|
|
11107
|
-
const eben = frisch.get(mediaRef);
|
|
11108
|
-
if (eben) return { kind: "ok", value: { data: eben.data, mime_type: eben.mimeType } };
|
|
11281
|
+
async resolveImage(mediaRef, mimeTypeHinweis) {
|
|
11109
11282
|
try {
|
|
11110
|
-
const
|
|
11111
|
-
|
|
11112
|
-
if (!eintrag) {
|
|
11113
|
-
return fehler2(
|
|
11114
|
-
`Das Bild ${mediaRef} steht nicht im Bestand. Moeglicherweise hat der Abgleich es noch nicht uebertragen.`,
|
|
11115
|
-
true
|
|
11116
|
-
);
|
|
11117
|
-
}
|
|
11118
|
-
const base64 = await hfLoadImageAsBase64(
|
|
11119
|
-
mediaRef,
|
|
11120
|
-
token,
|
|
11121
|
-
void 0,
|
|
11122
|
-
eintrag.filename,
|
|
11123
|
-
void 0,
|
|
11124
|
-
eintrag.mimeType,
|
|
11125
|
-
false
|
|
11126
|
-
);
|
|
11127
|
-
if (!base64) {
|
|
11128
|
-
return fehler2(`Das Bild ${mediaRef} ist im Bestand verzeichnet, aber nicht ladbar.`, true);
|
|
11129
|
-
}
|
|
11130
|
-
return { kind: "ok", value: { data: base64, mime_type: eintrag.mimeType || "image/jpeg" } };
|
|
11283
|
+
const bild = await store.resolve(mediaRef, mimeTypeHinweis);
|
|
11284
|
+
return { kind: "ok", value: { data: bild.data, mime_type: bild.mimeType } };
|
|
11131
11285
|
} catch (error) {
|
|
11132
|
-
return fehler2(
|
|
11133
|
-
`Das Bild ${mediaRef} konnte nicht geladen werden: ${error instanceof Error ? error.message : String(error)}`,
|
|
11134
|
-
true
|
|
11135
|
-
);
|
|
11286
|
+
return fehler2(error instanceof Error ? error.message : String(error), true);
|
|
11136
11287
|
}
|
|
11137
11288
|
},
|
|
11138
11289
|
async putImage(input) {
|
|
11139
11290
|
const id = newImageId();
|
|
11140
11291
|
try {
|
|
11141
|
-
await
|
|
11142
|
-
await writeHFEvent(namespace, token, "image_added", {
|
|
11143
|
-
id,
|
|
11144
|
-
prompt: input.title,
|
|
11145
|
-
tags: [],
|
|
11146
|
-
timestamp: now(),
|
|
11147
|
-
mimeType: input.mime_type
|
|
11148
|
-
}, []);
|
|
11149
|
-
frisch.set(id, { mimeType: input.mime_type, data: input.data });
|
|
11292
|
+
await store.putWithId(id, input.data, input.mime_type, input.title);
|
|
11150
11293
|
return {
|
|
11151
11294
|
kind: "ok",
|
|
11152
11295
|
value: { mediaRef: id, title: input.title, mimeType: input.mime_type, thumbUrl: null }
|
|
@@ -11276,6 +11419,11 @@ function alsBilder(rohe) {
|
|
|
11276
11419
|
media_ref: b.media_ref,
|
|
11277
11420
|
position: b.position,
|
|
11278
11421
|
...istText4(b.asset_id) ? { asset_id: b.asset_id } : {},
|
|
11422
|
+
// Der bestätigte MIME-Typ (Review 2026-08-18 §5 P2) muss durch das
|
|
11423
|
+
// Rücklesen hindurch: Genau hier braucht ihn der Lesepfad, um den
|
|
11424
|
+
// Dateipfad `images/<id>.<ext>` zu bilden, statt ihn zu erraten. Nur
|
|
11425
|
+
// gesetzt, wenn er im Ereignis steht — ältere Batches tragen ihn nicht.
|
|
11426
|
+
...istText4(b.mime_type) ? { mime_type: b.mime_type } : {},
|
|
11279
11427
|
model: b.model ?? null,
|
|
11280
11428
|
seed: b.seed ?? null,
|
|
11281
11429
|
width: b.width ?? null,
|
|
@@ -11364,6 +11512,7 @@ async function legeBatchAb(options, input) {
|
|
|
11364
11512
|
const { namespace, token, channel } = options;
|
|
11365
11513
|
const newImageId = options.newImageId ?? ((batchId, position) => `${batchId}-${position}`);
|
|
11366
11514
|
const now = options.now ?? (() => /* @__PURE__ */ new Date());
|
|
11515
|
+
const store = options.store ?? createHfImageStore({ namespace, token });
|
|
11367
11516
|
const itemId = itemIdForRun(input.runId);
|
|
11368
11517
|
let vorhandeneEvents;
|
|
11369
11518
|
try {
|
|
@@ -11382,15 +11531,14 @@ async function legeBatchAb(options, input) {
|
|
|
11382
11531
|
for (let offset = 0; offset < input.images.length; offset++) {
|
|
11383
11532
|
const bild = input.images[offset];
|
|
11384
11533
|
const id = newImageId(input.generationBatchId, startPosition + offset);
|
|
11534
|
+
const echterTyp = typAusBytes(bild.imageBase64, bild.mimeType);
|
|
11385
11535
|
try {
|
|
11386
|
-
await
|
|
11387
|
-
await writeHFEvent(namespace, token, "image_added", {
|
|
11536
|
+
await store.putWithId(
|
|
11388
11537
|
id,
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
|
|
11393
|
-
}, []);
|
|
11538
|
+
bild.imageBase64,
|
|
11539
|
+
echterTyp,
|
|
11540
|
+
input.title ?? `Batch ${input.generationBatchId}`
|
|
11541
|
+
);
|
|
11394
11542
|
} catch (error) {
|
|
11395
11543
|
return fehler3(
|
|
11396
11544
|
`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.`
|
|
@@ -11400,6 +11548,7 @@ async function legeBatchAb(options, input) {
|
|
|
11400
11548
|
position: startPosition + offset,
|
|
11401
11549
|
media_ref: id,
|
|
11402
11550
|
asset_id: id,
|
|
11551
|
+
mime_type: echterTyp,
|
|
11403
11552
|
model: bild.model ?? null,
|
|
11404
11553
|
seed: bild.seed ?? null,
|
|
11405
11554
|
width: bild.width ?? null,
|
|
@@ -11443,8 +11592,11 @@ function createHfImageGenerationBatchPersistence(options) {
|
|
|
11443
11592
|
images: input.images.map((bild) => ({
|
|
11444
11593
|
imageBase64: bild.imageBase64,
|
|
11445
11594
|
// Flow liefert PNG-Base64 (bestehende Konvention, s. AvatarArchitectApp.tsx
|
|
11446
|
-
// `data:image/png;base64,${base64}`)
|
|
11447
|
-
// keinen MIME-Typ je Bild.
|
|
11595
|
+
// `data:image/png;base64,${base64}`), und der gemeinsame Vertrag führt
|
|
11596
|
+
// keinen MIME-Typ je Bild. Das ist deshalb nur die **Vorgabe**:
|
|
11597
|
+
// Entschieden wird nach den echten Bytes (Review §5 P2) — ein künftig
|
|
11598
|
+
// anders kodiertes Bild läge sonst unter einer Endung, unter der es
|
|
11599
|
+
// niemand sucht.
|
|
11448
11600
|
mimeType: "image/png",
|
|
11449
11601
|
model: bild.model ?? null,
|
|
11450
11602
|
seed: bild.seed ?? null,
|
|
@@ -11465,6 +11617,8 @@ function createHfImageBatchWrite(options) {
|
|
|
11465
11617
|
title: input.title,
|
|
11466
11618
|
images: input.images.map((bild) => ({
|
|
11467
11619
|
imageBase64: bild.imageBase64,
|
|
11620
|
+
// Vorgabe, kein Urteil — der Import bringt beliebig kodierte Bilder
|
|
11621
|
+
// mit, und der Typ wird aus den Bytes bestimmt (Review §5 P2).
|
|
11468
11622
|
mimeType: "image/png",
|
|
11469
11623
|
model: bild.model ?? null,
|
|
11470
11624
|
seed: bild.seed ?? null,
|
|
@@ -11753,7 +11907,17 @@ function createFlowSzenenViewPort(options) {
|
|
|
11753
11907
|
...options.newRunId ? { newRunId: options.newRunId } : {},
|
|
11754
11908
|
...options.now ? { now: options.now } : {}
|
|
11755
11909
|
});
|
|
11756
|
-
const
|
|
11910
|
+
const hatHfZugangsdaten = Boolean(options.namespace?.trim() && options.token?.trim());
|
|
11911
|
+
const bildSpeicher = hatHfZugangsdaten ? createHfImageStore({
|
|
11912
|
+
namespace: options.namespace,
|
|
11913
|
+
token: options.token,
|
|
11914
|
+
...options.now ? { now: () => options.now().getTime() } : {}
|
|
11915
|
+
}) : void 0;
|
|
11916
|
+
const imageLibrary = options.imageLibrary ?? (bildSpeicher ? createHfImageLibrary({
|
|
11917
|
+
namespace: options.namespace,
|
|
11918
|
+
token: options.token,
|
|
11919
|
+
store: bildSpeicher
|
|
11920
|
+
}) : void 0);
|
|
11757
11921
|
const derivation = createClientDerivationPort({
|
|
11758
11922
|
store: elements,
|
|
11759
11923
|
derivations: createEventLogDerivationPersistence(channel),
|
|
@@ -11763,11 +11927,11 @@ function createFlowSzenenViewPort(options) {
|
|
|
11763
11927
|
...options.now ? { now: options.now } : {}
|
|
11764
11928
|
});
|
|
11765
11929
|
const imageBatchHistory = createHfImageBatchHistory({ channel });
|
|
11766
|
-
const
|
|
11767
|
-
const imageBatchWrite = hatHfZugangsdaten ? createHfImageBatchWrite({
|
|
11930
|
+
const imageBatchWrite = bildSpeicher ? createHfImageBatchWrite({
|
|
11768
11931
|
namespace: options.namespace,
|
|
11769
11932
|
token: options.token,
|
|
11770
11933
|
channel,
|
|
11934
|
+
store: bildSpeicher,
|
|
11771
11935
|
...options.newBatchImageId ? { newImageId: options.newBatchImageId } : {},
|
|
11772
11936
|
...options.now ? { now: options.now } : {}
|
|
11773
11937
|
}) : void 0;
|
|
@@ -11781,6 +11945,9 @@ function createFlowSzenenViewPort(options) {
|
|
|
11781
11945
|
namespace: options.namespace,
|
|
11782
11946
|
token: options.token,
|
|
11783
11947
|
channel,
|
|
11948
|
+
// Dieselbe Instanz wie der Bildbestand — sonst wäre das gerade
|
|
11949
|
+
// erzeugte Bild in der Laufansicht wieder unauffindbar (R1).
|
|
11950
|
+
store: bildSpeicher,
|
|
11784
11951
|
...options.newBatchImageId ? { newImageId: options.newBatchImageId } : {},
|
|
11785
11952
|
...options.now ? { now: options.now } : {}
|
|
11786
11953
|
}),
|
|
@@ -11796,6 +11963,7 @@ function createFlowSzenenViewPort(options) {
|
|
|
11796
11963
|
}
|
|
11797
11964
|
|
|
11798
11965
|
export {
|
|
11966
|
+
applyEvents,
|
|
11799
11967
|
capabilitiesOf,
|
|
11800
11968
|
unsupportedReason,
|
|
11801
11969
|
callOptional,
|
|
@@ -11910,6 +12078,9 @@ export {
|
|
|
11910
12078
|
runPromptDerivation,
|
|
11911
12079
|
createEventLogRunPersistence,
|
|
11912
12080
|
createClientRunPort,
|
|
12081
|
+
bildPfad,
|
|
12082
|
+
typAusBytes,
|
|
12083
|
+
createHfImageStore,
|
|
11913
12084
|
createHfImageLibrary,
|
|
11914
12085
|
FLOW_MODEL_DISPLAY_NAMES,
|
|
11915
12086
|
flowImageProviderHasAccess,
|
|
@@ -15,6 +15,21 @@ function treeUrl(namespace, subdir = "") {
|
|
|
15
15
|
var DROSSEL_VERSUCHE = 4;
|
|
16
16
|
var DROSSEL_BASIS_MS = 400;
|
|
17
17
|
var schlafen = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
18
|
+
var HF_LESE_ZEITLIMIT_MS = 2e4;
|
|
19
|
+
async function holeMitZeitlimit(url, init) {
|
|
20
|
+
const abbruch = new AbortController();
|
|
21
|
+
const timer = setTimeout(() => abbruch.abort(), HF_LESE_ZEITLIMIT_MS);
|
|
22
|
+
try {
|
|
23
|
+
return await fetch(url, { ...init, signal: abbruch.signal });
|
|
24
|
+
} catch (error) {
|
|
25
|
+
if (abbruch.signal.aborted) {
|
|
26
|
+
throw new Error(`HF-Anfrage ohne Antwort nach ${HF_LESE_ZEITLIMIT_MS}ms abgebrochen: ${url}`);
|
|
27
|
+
}
|
|
28
|
+
throw error;
|
|
29
|
+
} finally {
|
|
30
|
+
clearTimeout(timer);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
18
33
|
async function mitGeduld(anfrage) {
|
|
19
34
|
let letzte = null;
|
|
20
35
|
for (let versuch = 0; versuch < DROSSEL_VERSUCHE; versuch += 1) {
|
|
@@ -29,7 +44,7 @@ async function mitGeduld(anfrage) {
|
|
|
29
44
|
return letzte;
|
|
30
45
|
}
|
|
31
46
|
async function hfListDir(namespace, subdir, token) {
|
|
32
|
-
const res = await mitGeduld(() =>
|
|
47
|
+
const res = await mitGeduld(() => holeMitZeitlimit(treeUrl(namespace, subdir), {
|
|
33
48
|
headers: { Authorization: `Bearer ${token}` }
|
|
34
49
|
}));
|
|
35
50
|
if (res.status === 404) return [];
|
|
@@ -37,7 +52,7 @@ async function hfListDir(namespace, subdir, token) {
|
|
|
37
52
|
return res.json();
|
|
38
53
|
}
|
|
39
54
|
async function hfDownloadJsonByPath(repoPath, token) {
|
|
40
|
-
const res = await mitGeduld(() =>
|
|
55
|
+
const res = await mitGeduld(() => holeMitZeitlimit(
|
|
41
56
|
`${HF_BASE}/datasets/${HF_REPO}/resolve/main/${repoPath}?download=true`,
|
|
42
57
|
{ headers: { Authorization: `Bearer ${token}` } }
|
|
43
58
|
));
|
|
@@ -45,7 +60,7 @@ async function hfDownloadJsonByPath(repoPath, token) {
|
|
|
45
60
|
return res.json();
|
|
46
61
|
}
|
|
47
62
|
async function hfDownloadBinaryByPath(repoPath, token) {
|
|
48
|
-
const res = await mitGeduld(() =>
|
|
63
|
+
const res = await mitGeduld(() => holeMitZeitlimit(
|
|
49
64
|
`${HF_BASE}/datasets/${HF_REPO}/resolve/main/${repoPath}?download=true`,
|
|
50
65
|
{ headers: { Authorization: `Bearer ${token}` } }
|
|
51
66
|
));
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
import { T as TextGenerationPort } from './contracts-DdYOMBl9.js';
|
|
2
|
+
|
|
3
|
+
interface TagOption {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
is_user_created?: boolean;
|
|
7
|
+
is_deleted?: boolean;
|
|
8
|
+
}
|
|
9
|
+
interface WorkspaceTags {
|
|
10
|
+
by_category: Record<string, TagOption[]>;
|
|
11
|
+
all: Array<TagOption & {
|
|
12
|
+
category: string;
|
|
13
|
+
}>;
|
|
14
|
+
}
|
|
15
|
+
interface Generation {
|
|
16
|
+
id: string;
|
|
17
|
+
nodeId: string;
|
|
18
|
+
base64?: string;
|
|
19
|
+
fullBase64?: string;
|
|
20
|
+
mediaId?: string;
|
|
21
|
+
prompt?: string;
|
|
22
|
+
hierarchy?: string;
|
|
23
|
+
seed?: number;
|
|
24
|
+
model?: string;
|
|
25
|
+
timestamp: number;
|
|
26
|
+
status: 'processing' | 'done' | 'error';
|
|
27
|
+
step?: string;
|
|
28
|
+
tags: string[];
|
|
29
|
+
type?: 'generation' | 'import';
|
|
30
|
+
error?: {
|
|
31
|
+
message: string;
|
|
32
|
+
details?: string;
|
|
33
|
+
};
|
|
34
|
+
selectedForExport?: boolean;
|
|
35
|
+
filename?: string;
|
|
36
|
+
hasThumb?: boolean;
|
|
37
|
+
mimeType?: string;
|
|
38
|
+
titleTs?: number;
|
|
39
|
+
}
|
|
40
|
+
interface ProjectSettings {
|
|
41
|
+
aspectRatio: string;
|
|
42
|
+
selectedModel: string;
|
|
43
|
+
seed: number;
|
|
44
|
+
seedMode: 'random' | 'fixed';
|
|
45
|
+
}
|
|
46
|
+
interface ProjectMeta {
|
|
47
|
+
id: string;
|
|
48
|
+
name: string;
|
|
49
|
+
saved_at: string;
|
|
50
|
+
size: number;
|
|
51
|
+
}
|
|
52
|
+
interface SyncDiff {
|
|
53
|
+
localOnly: Generation[];
|
|
54
|
+
serverOnly: Generation[];
|
|
55
|
+
}
|
|
56
|
+
interface LabFrame {
|
|
57
|
+
id: string;
|
|
58
|
+
base64: string;
|
|
59
|
+
mediaId?: string;
|
|
60
|
+
seed?: number;
|
|
61
|
+
model?: string;
|
|
62
|
+
aspectRatio?: string;
|
|
63
|
+
width?: number;
|
|
64
|
+
height?: number;
|
|
65
|
+
source?: 'generated' | 'flow-gallery' | 'zip-import' | 'db-library';
|
|
66
|
+
}
|
|
67
|
+
interface LabItem {
|
|
68
|
+
id: string;
|
|
69
|
+
prompt: string;
|
|
70
|
+
label?: string;
|
|
71
|
+
tags?: string[];
|
|
72
|
+
frames: LabFrame[];
|
|
73
|
+
}
|
|
74
|
+
interface SelectedLabImage {
|
|
75
|
+
item: LabItem;
|
|
76
|
+
frame: LabFrame;
|
|
77
|
+
label: string;
|
|
78
|
+
roleForPrompt?: string;
|
|
79
|
+
roleForImage?: string;
|
|
80
|
+
sendToPromptAI: boolean;
|
|
81
|
+
sendToImageGen: boolean;
|
|
82
|
+
}
|
|
83
|
+
interface LabServices {
|
|
84
|
+
availableItems: LabItem[];
|
|
85
|
+
recentItems: LabItem[];
|
|
86
|
+
onItemUsed: (item: LabItem) => void;
|
|
87
|
+
generateText: (text: string, options?: {
|
|
88
|
+
images?: {
|
|
89
|
+
base64: string;
|
|
90
|
+
mimeType: string;
|
|
91
|
+
}[];
|
|
92
|
+
systemInstruction?: string;
|
|
93
|
+
}) => Promise<string>;
|
|
94
|
+
generateImage: (options: Record<string, any>) => Promise<{
|
|
95
|
+
base64: string;
|
|
96
|
+
mediaId?: string;
|
|
97
|
+
}>;
|
|
98
|
+
saveResult?: (item: LabItem) => Promise<void>;
|
|
99
|
+
workspaceTags?: WorkspaceTags;
|
|
100
|
+
}
|
|
101
|
+
interface HFMetadataEntry {
|
|
102
|
+
id: string;
|
|
103
|
+
prompt?: string;
|
|
104
|
+
seed?: number;
|
|
105
|
+
model?: string;
|
|
106
|
+
tags: string[];
|
|
107
|
+
timestamp: number;
|
|
108
|
+
mimeType: string;
|
|
109
|
+
size?: number;
|
|
110
|
+
filename?: string;
|
|
111
|
+
hasThumb?: boolean;
|
|
112
|
+
titleTs?: number;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
declare function buildGenerationPrompt(hierarchyText: string, mode?: 'literal' | 'creative'): string;
|
|
116
|
+
declare function buildFallbackPrompt(hierarchyText: string): string;
|
|
117
|
+
declare function cleanAiResponse(text: string): string;
|
|
118
|
+
declare function buildImageGenerationOptions(prompt: string, aspectRatio: string, model: string, referenceMediaId?: string): Record<string, any>;
|
|
119
|
+
interface SelectedTag {
|
|
120
|
+
label: string;
|
|
121
|
+
value: string;
|
|
122
|
+
category: string;
|
|
123
|
+
}
|
|
124
|
+
declare function buildPromptTabPayload(selectedTags: SelectedTag[], instructions: string, rules: string, treeText?: string): string;
|
|
125
|
+
declare function parsePromptResponse(raw: string): {
|
|
126
|
+
prompt: string;
|
|
127
|
+
feedback: string | null;
|
|
128
|
+
};
|
|
129
|
+
interface FlowSdkImage {
|
|
130
|
+
base64: string;
|
|
131
|
+
mimeType: string;
|
|
132
|
+
}
|
|
133
|
+
interface FlowTextGenerationOptions {
|
|
134
|
+
images?: FlowSdkImage[];
|
|
135
|
+
systemInstruction?: string;
|
|
136
|
+
responseFormat?: 'text' | 'json';
|
|
137
|
+
thinkingLevel?: 'low' | 'medium' | 'high';
|
|
138
|
+
}
|
|
139
|
+
interface FlowSdk {
|
|
140
|
+
generate: {
|
|
141
|
+
image: (options: Record<string, any>) => Promise<{
|
|
142
|
+
base64: string;
|
|
143
|
+
mediaId: string;
|
|
144
|
+
}>;
|
|
145
|
+
text: (prompt: string, options?: {
|
|
146
|
+
systemInstruction?: string;
|
|
147
|
+
thinkingLevel?: string;
|
|
148
|
+
images?: FlowSdkImage[];
|
|
149
|
+
}) => Promise<{
|
|
150
|
+
text: string;
|
|
151
|
+
}>;
|
|
152
|
+
};
|
|
153
|
+
download: (args: {
|
|
154
|
+
base64: string;
|
|
155
|
+
mimeType: string;
|
|
156
|
+
filename: string;
|
|
157
|
+
}) => Promise<void>;
|
|
158
|
+
media: {
|
|
159
|
+
selectMultiple: (args: {
|
|
160
|
+
filter: string;
|
|
161
|
+
}) => Promise<any[]>;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
declare function createFlowServices(Flow: FlowSdk): {
|
|
165
|
+
generateImage: (options: Record<string, any>) => Promise<{
|
|
166
|
+
base64: string;
|
|
167
|
+
mediaId: string;
|
|
168
|
+
}>;
|
|
169
|
+
generateText: (text: string, options?: FlowTextGenerationOptions) => Promise<string>;
|
|
170
|
+
};
|
|
171
|
+
declare function interpretSdkError(err: any): Error;
|
|
172
|
+
|
|
173
|
+
type FlowGenerateText = (prompt: string, options?: FlowTextGenerationOptions) => Promise<string>;
|
|
174
|
+
interface CreateFlowTextGenerationPortOptions {
|
|
175
|
+
provider?: string;
|
|
176
|
+
modelId?: string;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Adapts the existing Flow SDK service to the host-neutral Szenen contract.
|
|
180
|
+
* It deliberately does not parse or validate the response: that happens once
|
|
181
|
+
* in `runPromptDerivation`, identically for every host.
|
|
182
|
+
*/
|
|
183
|
+
declare function createFlowTextGenerationPort(generateText: FlowGenerateText, options?: CreateFlowTextGenerationPortOptions): TextGenerationPort;
|
|
184
|
+
|
|
185
|
+
interface HFEventVersion {
|
|
186
|
+
major: number;
|
|
187
|
+
minor: number;
|
|
188
|
+
}
|
|
189
|
+
interface HFEvent<P = unknown> {
|
|
190
|
+
v: HFEventVersion;
|
|
191
|
+
type: string;
|
|
192
|
+
ts: number;
|
|
193
|
+
prevTs: number[];
|
|
194
|
+
clientId: string;
|
|
195
|
+
payload: P;
|
|
196
|
+
}
|
|
197
|
+
interface HFStateMeta {
|
|
198
|
+
consolidatedAt: number;
|
|
199
|
+
version: number;
|
|
200
|
+
}
|
|
201
|
+
interface HFStateSnapshot {
|
|
202
|
+
metadata: HFMetadataEntry[];
|
|
203
|
+
tags: WorkspaceTags;
|
|
204
|
+
meta: HFStateMeta;
|
|
205
|
+
openTasks?: Record<string, TaskRequestedPayload>;
|
|
206
|
+
}
|
|
207
|
+
interface HFFileInfo {
|
|
208
|
+
type: 'file' | 'directory';
|
|
209
|
+
path: string;
|
|
210
|
+
size: number;
|
|
211
|
+
}
|
|
212
|
+
interface ImageAddedPayload extends HFMetadataEntry {
|
|
213
|
+
taskId?: string;
|
|
214
|
+
}
|
|
215
|
+
interface TagUpsertedPayload {
|
|
216
|
+
category: string;
|
|
217
|
+
label: string;
|
|
218
|
+
value: string;
|
|
219
|
+
is_user_created?: boolean;
|
|
220
|
+
is_deleted?: boolean;
|
|
221
|
+
}
|
|
222
|
+
interface MetadataUpdatedPayload {
|
|
223
|
+
id: string;
|
|
224
|
+
delta: Partial<HFMetadataEntry>;
|
|
225
|
+
}
|
|
226
|
+
interface TaskRequestedPayload {
|
|
227
|
+
taskId: string;
|
|
228
|
+
taskType: string;
|
|
229
|
+
params: {
|
|
230
|
+
prompt: string;
|
|
231
|
+
tags?: string[];
|
|
232
|
+
book?: string;
|
|
233
|
+
kapitel?: string;
|
|
234
|
+
ankerId?: string;
|
|
235
|
+
promptVersion?: number;
|
|
236
|
+
[key: string]: any;
|
|
237
|
+
};
|
|
238
|
+
expiresAt?: number;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
export { type CreateFlowTextGenerationPortOptions as C, type FlowGenerateText as F, type Generation as G, type HFEvent as H, type ImageAddedPayload as I, type LabFrame as L, type MetadataUpdatedPayload as M, type ProjectMeta as P, type SelectedLabImage as S, type TagOption as T, type WorkspaceTags as W, type FlowSdk as a, type FlowTextGenerationOptions as b, type HFEventVersion as c, type HFFileInfo as d, type HFMetadataEntry as e, type HFStateMeta as f, type HFStateSnapshot as g, type LabItem as h, type LabServices as i, type ProjectSettings as j, type SelectedTag as k, type SyncDiff as l, type TagUpsertedPayload as m, buildFallbackPrompt as n, buildGenerationPrompt as o, buildImageGenerationOptions as p, buildPromptTabPayload as q, cleanAiResponse as r, createFlowServices as s, createFlowTextGenerationPort as t, interpretSdkError as u, parsePromptResponse as v };
|