@rslsp1/fa-app-tools 10.3.3 → 10.3.5

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/index.js CHANGED
@@ -22,7 +22,7 @@ require('./chunk-FTLEDU6C.js');
22
22
  require('./chunk-DDH2SGZM.js');
23
23
 
24
24
  // package.json
25
- var version = "10.3.3";
25
+ var version = "10.3.5";
26
26
 
27
27
  // src/hooks/useOnClickOutside.ts
28
28
  var _react = require('react'); var _react2 = _interopRequireDefault(_react);
@@ -5465,7 +5465,7 @@ function ServerTab({ serverBaseUrl }) {
5465
5465
  function FlowWorkspacePicker({
5466
5466
  tagBase,
5467
5467
  selectedUserId,
5468
- message,
5468
+ message: message3,
5469
5469
  onSelectUser,
5470
5470
  onSelectContext
5471
5471
  }) {
@@ -5489,7 +5489,7 @@ function FlowWorkspacePicker({
5489
5489
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "strong", { children: "FineArt Flow" }),
5490
5490
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "small", { children: step === "user" ? "Benutzer w\xE4hlen" : `Kontext f\xFCr ${_nullishCoalesce(_optionalChain([selectedUser, 'optionalAccess', _153 => _153.username]), () => ( `User ${selectedUserId}`))}` })
5491
5491
  ] }),
5492
- message && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "flow-workspace-picker__warning", children: message }),
5492
+ message3 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "flow-workspace-picker__warning", children: message3 }),
5493
5493
  step === "user" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flow-workspace-picker__choices", "aria-label": "Benutzer w\xE4hlen", children: [
5494
5494
  tagBase.users.map((user) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { type: "button", onClick: () => chooseUser(user.id), children: [
5495
5495
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: user.username }),
@@ -5538,6 +5538,7 @@ var FLOW_BRIDGE_REQUEST_EVENT = "fine-art-flow-bridge:request:v1";
5538
5538
  var FLOW_BRIDGE_RESPONSE_EVENT = "fine-art-flow-bridge:response:v1";
5539
5539
  var FLOW_BRIDGE_HELLO_TIMEOUT_MS = 1500;
5540
5540
  var FLOW_BRIDGE_REQUEST_TIMEOUT_MS = 15e3;
5541
+ var FLOW_BRIDGE_CONNECT_TIMEOUT_MS = 3e5;
5541
5542
  function isRecord(value) {
5542
5543
  return value !== null && typeof value === "object" && !Array.isArray(value);
5543
5544
  }
@@ -5604,12 +5605,23 @@ function createFlowBridgeClient({
5604
5605
  }
5605
5606
  return { available: true, name: bridge.name, version: bridge.version, protocol: bridge.protocol, roundTripMs };
5606
5607
  },
5607
- async request(request) {
5608
+ async connect(env, { timeoutMs = FLOW_BRIDGE_CONNECT_TIMEOUT_MS } = {}) {
5608
5609
  const started = clock();
5609
- const reply = await exchange({ op: "request", target: request.target, method: request.method, path: request.path }, requestTimeoutMs);
5610
+ const reply = await exchange({ op: "connect", env }, timeoutMs);
5611
+ const waitedMs = Math.round(clock() - started);
5612
+ if (!reply) {
5613
+ return { ok: false, error: { code: "no-bridge", message: `Keine Freigabe innerhalb von ${Math.round(timeoutMs / 1e3)} s \u2014 Extension fehlt, Frame nicht freigegeben oder Popup nicht bestaetigt.` }, waitedMs };
5614
+ }
5615
+ if (reply.ok !== true || reply.env !== env || typeof reply.server !== "string") return { ok: false, error: readError(reply.error), waitedMs };
5616
+ return { ok: true, env, server: reply.server, waitedMs };
5617
+ },
5618
+ async request(request, { timeoutMs = requestTimeoutMs } = {}) {
5619
+ const started = clock();
5620
+ const tokenSuffix = "tokenSuffix" in request && request.tokenSuffix !== void 0 ? { tokenSuffix: request.tokenSuffix } : {};
5621
+ const reply = await exchange({ op: "request", target: request.target, method: request.method, path: request.path, ...tokenSuffix }, timeoutMs);
5610
5622
  const roundTripMs = Math.round(clock() - started);
5611
5623
  if (!reply) {
5612
- return { ok: false, transport: null, status: null, data: null, latencyMs: null, roundTripMs, error: noBridge(requestTimeoutMs) };
5624
+ return { ok: false, transport: null, status: null, data: null, latencyMs: null, roundTripMs, error: noBridge(timeoutMs) };
5613
5625
  }
5614
5626
  const ok = reply.ok === true;
5615
5627
  return {
@@ -5625,13 +5637,130 @@ function createFlowBridgeClient({
5625
5637
  };
5626
5638
  }
5627
5639
 
5640
+ // src/lib/flowProbeLoader.ts
5641
+ var FLOW_PROBE_REQUEST = { target: "devMcp", method: "GET", path: "/flow-app/probe-bundle" };
5642
+ var HF_TOKEN_SUFFIX_CHARS = 8;
5643
+ var FLOW_PROBE_MARKER = "__faFlowProbe";
5644
+ var FLOW_PROBE_METHOD = "script-blob";
5645
+ var FLOW_PROBE_LOAD_TIMEOUT_MS = 5e3;
5646
+ var CSP_SETTLE_MS = 100;
5647
+ function isRecord2(value) {
5648
+ return value !== null && typeof value === "object" && !Array.isArray(value);
5649
+ }
5650
+ function hfTokenSuffix(token) {
5651
+ const trimmed = (_nullishCoalesce(token, () => ( ""))).trim();
5652
+ return trimmed.length >= HF_TOKEN_SUFFIX_CHARS ? trimmed.slice(-HF_TOKEN_SUFFIX_CHARS) : null;
5653
+ }
5654
+ function readFlowProbeBundle(data) {
5655
+ if (!isRecord2(data)) return null;
5656
+ const { version: version2, sha256, source } = data;
5657
+ if (typeof version2 !== "string" || !/^probe-\d{3}$/.test(version2)) return null;
5658
+ if (typeof sha256 !== "string" || !/^[0-9a-f]{64}$/.test(sha256)) return null;
5659
+ if (typeof source !== "string" || source.length === 0) return null;
5660
+ return { version: version2, sha256, source };
5661
+ }
5662
+ function readMarker(value) {
5663
+ if (!isRecord2(value) || value.executed !== true || typeof value.version !== "string") return null;
5664
+ return { executed: true, version: value.version, executedAt: typeof value.executedAt === "string" ? value.executedAt : null };
5665
+ }
5666
+ async function sha256Hex(text) {
5667
+ if (!_optionalChain([globalThis, 'access', _154 => _154.crypto, 'optionalAccess', _155 => _155.subtle])) throw new Error("crypto.subtle ist in diesem Kontext nicht verfuegbar.");
5668
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
5669
+ return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
5670
+ }
5671
+ var message = (error) => error instanceof Error ? error.message : String(error);
5672
+ var wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5673
+ async function executeFlowProbeBundle(bundle, {
5674
+ win = window,
5675
+ doc = document,
5676
+ timeoutMs = FLOW_PROBE_LOAD_TIMEOUT_MS,
5677
+ digest = sha256Hex
5678
+ } = {}) {
5679
+ const markerHost = win;
5680
+ const result = {
5681
+ method: FLOW_PROBE_METHOD,
5682
+ pageOrigin: win.location.origin,
5683
+ hash: { expected: bundle.sha256, actual: null, matches: null, error: null },
5684
+ scriptEvent: "not-started",
5685
+ marker: null,
5686
+ executed: false,
5687
+ cspViolations: [],
5688
+ error: null
5689
+ };
5690
+ try {
5691
+ result.hash.actual = await digest(bundle.source);
5692
+ result.hash.matches = result.hash.actual === bundle.sha256;
5693
+ } catch (error) {
5694
+ result.hash.error = message(error);
5695
+ }
5696
+ if (result.hash.matches === false) {
5697
+ result.error = "SHA-256 des empfangenen Quelltexts weicht ab \u2014 Bundle nicht ausgefuehrt.";
5698
+ return result;
5699
+ }
5700
+ delete markerHost[FLOW_PROBE_MARKER];
5701
+ const onViolation = (event) => {
5702
+ const violation = event;
5703
+ result.cspViolations.push(`${violation.effectiveDirective || violation.violatedDirective}: ${violation.blockedURI || "unbekannt"}`);
5704
+ };
5705
+ doc.addEventListener("securitypolicyviolation", onViolation);
5706
+ let url = null;
5707
+ let script = null;
5708
+ try {
5709
+ url = URL.createObjectURL(new Blob([bundle.source], { type: "text/javascript" }));
5710
+ const element = doc.createElement("script");
5711
+ script = element;
5712
+ result.scriptEvent = await new Promise((resolve) => {
5713
+ const timer = setTimeout(() => resolve("timeout"), timeoutMs);
5714
+ element.addEventListener("load", () => {
5715
+ clearTimeout(timer);
5716
+ resolve("load");
5717
+ });
5718
+ element.addEventListener("error", () => {
5719
+ clearTimeout(timer);
5720
+ resolve("error");
5721
+ });
5722
+ element.src = url;
5723
+ (_nullishCoalesce(doc.head, () => ( doc.documentElement))).appendChild(element);
5724
+ });
5725
+ } catch (error) {
5726
+ result.error = `Skript nicht einfuegbar: ${message(error)}`;
5727
+ }
5728
+ result.marker = readMarker(markerHost[FLOW_PROBE_MARKER]);
5729
+ result.executed = result.marker !== null && result.marker.version === bundle.version;
5730
+ if (!result.executed) await wait(CSP_SETTLE_MS);
5731
+ doc.removeEventListener("securitypolicyviolation", onViolation);
5732
+ _optionalChain([script, 'optionalAccess', _156 => _156.remove, 'call', _157 => _157()]);
5733
+ if (url) URL.revokeObjectURL(url);
5734
+ if (!result.executed && !result.error) {
5735
+ if (result.marker) result.error = `Marker meldet Version ${result.marker.version}, erwartet ${bundle.version}.`;
5736
+ else if (result.scriptEvent === "load") result.error = "script.onload ohne Marker \u2014 Ausfuehrung nicht belegt.";
5737
+ else if (result.scriptEvent === "error") result.error = "script.onerror \u2014 Skript nicht geladen oder blockiert.";
5738
+ else result.error = `Kein Skript-Ereignis innerhalb von ${timeoutMs} ms.`;
5739
+ }
5740
+ return result;
5741
+ }
5742
+
5628
5743
  // src/components/FlowBridgePanel.tsx
5629
5744
 
5630
5745
  var STATUS_REQUEST = { target: "dev", method: "GET", path: "/api/status" };
5631
- var FlowBridgePanel = ({ appVersion, client }) => {
5746
+ function hashText(execution) {
5747
+ if (execution.hash.matches === true) return "Hash gepr\xFCft";
5748
+ if (execution.hash.matches === false) return `Hash ABWEICHEND (berechnet ${_optionalChain([execution, 'access', _158 => _158.hash, 'access', _159 => _159.actual, 'optionalAccess', _160 => _160.slice, 'call', _161 => _161(0, 12)])}\u2026)`;
5749
+ return `Hash nicht pr\xFCfbar (${execution.hash.error})`;
5750
+ }
5751
+ function probeVerdict(run) {
5752
+ if (_optionalChain([run, 'access', _162 => _162.execution, 'optionalAccess', _163 => _163.executed])) return { ok: true, text: `ERGEBNIS: ausgef\xFChrt (executed: true, ${_optionalChain([run, 'access', _164 => _164.execution, 'access', _165 => _165.marker, 'optionalAccess', _166 => _166.version])})` };
5753
+ if (!run.response.ok) {
5754
+ return { ok: false, text: `ERGEBNIS: nicht ausgef\xFChrt \u2014 ${_optionalChain([run, 'access', _167 => _167.response, 'access', _168 => _168.error, 'optionalAccess', _169 => _169.code]) === "no-hf-token" ? "kein HF-Token in FlowFA." : "Bundle nicht \xFCber die Bridge erhalten."}` };
5755
+ }
5756
+ if (!run.bundle) return { ok: false, text: "ERGEBNIS: nicht ausgef\xFChrt \u2014 Antwort ohne g\xFCltiges Bundle." };
5757
+ return { ok: false, text: `ERGEBNIS: nicht ausgef\xFChrt \u2014 ${_optionalChain([run, 'access', _170 => _170.execution, 'optionalAccess', _171 => _171.error])}` };
5758
+ }
5759
+ var FlowBridgePanel = ({ appVersion, client, hfToken }) => {
5632
5760
  const bridge = _react.useMemo.call(void 0, () => _nullishCoalesce(client, () => ( createFlowBridgeClient({ appVersion }))), [client, appVersion]);
5633
5761
  const [status, setStatus] = _react.useState.call(void 0, null);
5634
5762
  const [response, setResponse] = _react.useState.call(void 0, null);
5763
+ const [probe, setProbe] = _react.useState.call(void 0, null);
5635
5764
  const [busy, setBusy] = _react.useState.call(void 0, null);
5636
5765
  const checkStatus = async () => {
5637
5766
  setBusy("status");
@@ -5659,6 +5788,35 @@ var FlowBridgePanel = ({ appVersion, client }) => {
5659
5788
  setBusy(null);
5660
5789
  }
5661
5790
  };
5791
+ const runProbe = async () => {
5792
+ setBusy("probe");
5793
+ setProbe(null);
5794
+ try {
5795
+ const tokenSuffix = hfTokenSuffix(hfToken);
5796
+ if (!tokenSuffix) {
5797
+ setProbe({
5798
+ response: {
5799
+ ok: false,
5800
+ transport: null,
5801
+ status: null,
5802
+ data: null,
5803
+ latencyMs: null,
5804
+ roundTripMs: 0,
5805
+ error: { code: "no-hf-token", message: "Kein HF-Token in FlowFA gesetzt \u2014 ohne ihn kein Zugang zum Dev-MCP-Host." }
5806
+ },
5807
+ bundle: null,
5808
+ execution: null
5809
+ });
5810
+ return;
5811
+ }
5812
+ const response2 = await bridge.request({ ...FLOW_PROBE_REQUEST, tokenSuffix });
5813
+ const bundle = response2.ok ? readFlowProbeBundle(response2.data) : null;
5814
+ const execution = bundle ? await executeFlowProbeBundle(bundle) : null;
5815
+ setProbe({ response: response2, bundle, execution });
5816
+ } finally {
5817
+ setBusy(null);
5818
+ }
5819
+ };
5662
5820
  const buttonStyle = {
5663
5821
  height: 36,
5664
5822
  border: "1px solid rgba(255,255,255,0.12)",
@@ -5672,20 +5830,268 @@ var FlowBridgePanel = ({ appVersion, client }) => {
5672
5830
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", onClick: checkStatus, disabled: busy !== null, className: "rounded-lg text-[11px] font-bold disabled:opacity-40", style: buttonStyle, children: busy === "status" ? "Pr\xFCfe\u2026" : "Bridge pr\xFCfen" }),
5673
5831
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", onClick: runRequest, disabled: busy !== null, className: "rounded-lg text-[11px] font-bold disabled:opacity-40", style: buttonStyle, children: busy === "request" ? "L\xE4uft\u2026" : "Dev /api/status" })
5674
5832
  ] }),
5833
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", onClick: runProbe, disabled: busy !== null, className: "rounded-lg text-[11px] font-bold disabled:opacity-40", style: buttonStyle, children: busy === "probe" ? "L\xE4uft\u2026" : "Mini-Bundle laden & ausf\xFChren" }),
5675
5834
  status && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { role: "status", "data-testid": "flow-bridge-status", style: { color: status.available ? "#4ade80" : "#f87171" }, children: status.available ? `Bridge: verbunden \xB7 ${status.name} v${status.version} \xB7 Protokoll ${status.protocol} \xB7 ${status.roundTripMs} ms` : `Bridge: nicht verbunden \xB7 ${status.error.code}: ${status.error.message}` }),
5676
5835
  response && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-testid": "flow-bridge-response", className: "flex flex-col gap-1", children: [
5677
5836
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { style: { color: response.ok ? "#4ade80" : "#f87171" }, children: [
5678
5837
  `${STATUS_REQUEST.method} ${STATUS_REQUEST.path} (${STATUS_REQUEST.target}) \u2192 `,
5679
5838
  response.status !== null ? `HTTP ${response.status}` : "kein HTTP-Status",
5680
- response.ok ? "" : ` \xB7 ${_optionalChain([response, 'access', _154 => _154.error, 'optionalAccess', _155 => _155.code])}: ${_optionalChain([response, 'access', _156 => _156.error, 'optionalAccess', _157 => _157.message])}`
5839
+ response.ok ? "" : ` \xB7 ${_optionalChain([response, 'access', _172 => _172.error, 'optionalAccess', _173 => _173.code])}: ${_optionalChain([response, 'access', _174 => _174.error, 'optionalAccess', _175 => _175.message])}`
5681
5840
  ] }),
5682
5841
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-white/40", children: `Transport: ${_nullishCoalesce(response.transport, () => ( "keiner"))} \xB7 Server ${_nullishCoalesce(response.latencyMs, () => ( "\u2014"))} ms \xB7 gesamt ${response.roundTripMs} ms` }),
5683
5842
  response.ok && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "pre", { className: "text-white/60 whitespace-pre-wrap break-all bg-black/30 rounded-lg p-2", children: JSON.stringify(response.data, null, 2) })
5843
+ ] }),
5844
+ probe && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { "data-testid": "flow-bridge-probe", className: "flex flex-col gap-1", children: [
5845
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { style: { color: probe.response.ok ? "#4ade80" : "#f87171" }, children: [
5846
+ `${FLOW_PROBE_REQUEST.method} ${FLOW_PROBE_REQUEST.path} (${FLOW_PROBE_REQUEST.target}) \u2192 `,
5847
+ probe.response.status !== null ? `HTTP ${probe.response.status}` : "kein HTTP-Status",
5848
+ probe.response.ok ? "" : ` \xB7 ${_optionalChain([probe, 'access', _176 => _176.response, 'access', _177 => _177.error, 'optionalAccess', _178 => _178.code])}: ${_optionalChain([probe, 'access', _179 => _179.response, 'access', _180 => _180.error, 'optionalAccess', _181 => _181.message])}`
5849
+ ] }),
5850
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-white/40", children: `Transport: ${_nullishCoalesce(probe.response.transport, () => ( "keiner"))} \xB7 Server ${_nullishCoalesce(probe.response.latencyMs, () => ( "\u2014"))} ms \xB7 gesamt ${probe.response.roundTripMs} ms` }),
5851
+ probe.bundle && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "text-white/60 break-all", children: [
5852
+ `Bundle ${probe.bundle.version} \xB7 ${probe.bundle.source.length} Zeichen \xB7 SHA-256 ${probe.bundle.sha256.slice(0, 12)}\u2026`,
5853
+ probe.execution ? ` \xB7 ${hashText(probe.execution)}` : ""
5854
+ ] }),
5855
+ probe.execution && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5856
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-white/60 break-all", children: `Ausf\xFChrung: <script src=blob:> \xB7 Ereignis ${probe.execution.scriptEvent} \xB7 Seite ${probe.execution.pageOrigin}` }),
5857
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-white/60 break-all", children: `Marker window.${FLOW_PROBE_MARKER}: ${probe.execution.marker ? JSON.stringify(probe.execution.marker) : "fehlt"}` }),
5858
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "break-all", style: { color: probe.execution.cspViolations.length > 0 ? "#f87171" : "rgba(255,255,255,0.4)" }, children: probe.execution.cspViolations.length > 0 ? `CSP: ${probe.execution.cspViolations.join("; ")}` : "CSP: keine Verletzung gemeldet" })
5859
+ ] }),
5860
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "data-testid": "flow-bridge-probe-verdict", className: "font-bold", style: { color: probeVerdict(probe).ok ? "#4ade80" : "#f87171" }, children: probeVerdict(probe).text })
5684
5861
  ] })
5685
5862
  ] })
5686
5863
  ] });
5687
5864
  };
5688
5865
 
5866
+ // src/components/FlowFineArtApp.tsx
5867
+
5868
+
5869
+ // src/lib/flowAppLoader.ts
5870
+ var FLOW_APP_TARGETS = {
5871
+ dev: { bridgeTarget: "devMcp", backendUrl: "https://dev-app.art-by-rolands.de" },
5872
+ prod: { bridgeTarget: "prodMcp", backendUrl: "https://app.art-by-rolands.de" }
5873
+ };
5874
+ var FLOW_APP_FILES = ["react-runtime.js", "master.css", "app.js"];
5875
+ var FLOW_APP_REQUEST_TIMEOUT_MS = 75e3;
5876
+ var FLOW_APP_SCRIPT_TIMEOUT_MS = 15e3;
5877
+ var CSP_SETTLE_MS2 = 100;
5878
+ function isRecord3(value) {
5879
+ return value !== null && typeof value === "object" && !Array.isArray(value);
5880
+ }
5881
+ function readFlowAppFile(data, file) {
5882
+ if (!isRecord3(data)) return null;
5883
+ const { sha256, source } = data;
5884
+ if (data.file !== file) return null;
5885
+ if (typeof sha256 !== "string" || !/^[0-9a-f]{64}$/.test(sha256)) return null;
5886
+ if (typeof source !== "string" || source.length === 0) return null;
5887
+ return { file, sha256, source };
5888
+ }
5889
+ async function sha256Hex2(text) {
5890
+ if (!_optionalChain([globalThis, 'access', _182 => _182.crypto, 'optionalAccess', _183 => _183.subtle])) throw new Error("crypto.subtle ist in diesem Kontext nicht verfuegbar.");
5891
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", new TextEncoder().encode(text));
5892
+ return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
5893
+ }
5894
+ var message2 = (error) => error instanceof Error ? error.message : String(error);
5895
+ var wait2 = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
5896
+ async function runScriptBlob(source, doc, timeoutMs, step) {
5897
+ const onViolation = (event) => {
5898
+ const violation = event;
5899
+ step.cspViolations.push(`${violation.effectiveDirective || violation.violatedDirective}: ${violation.blockedURI || "unbekannt"}`);
5900
+ };
5901
+ doc.addEventListener("securitypolicyviolation", onViolation);
5902
+ let url = null;
5903
+ let script = null;
5904
+ try {
5905
+ url = URL.createObjectURL(new Blob([source], { type: "text/javascript" }));
5906
+ const element = doc.createElement("script");
5907
+ script = element;
5908
+ step.scriptEvent = await new Promise((resolve) => {
5909
+ const timer = setTimeout(() => resolve("timeout"), timeoutMs);
5910
+ element.addEventListener("load", () => {
5911
+ clearTimeout(timer);
5912
+ resolve("load");
5913
+ });
5914
+ element.addEventListener("error", () => {
5915
+ clearTimeout(timer);
5916
+ resolve("error");
5917
+ });
5918
+ element.src = url;
5919
+ (_nullishCoalesce(doc.head, () => ( doc.documentElement))).appendChild(element);
5920
+ });
5921
+ } catch (error) {
5922
+ step.error = `Skript nicht einfuegbar: ${message2(error)}`;
5923
+ }
5924
+ if (step.scriptEvent !== "load") await wait2(CSP_SETTLE_MS2);
5925
+ doc.removeEventListener("securitypolicyviolation", onViolation);
5926
+ _optionalChain([script, 'optionalAccess', _184 => _184.remove, 'call', _185 => _185()]);
5927
+ if (url) URL.revokeObjectURL(url);
5928
+ }
5929
+ function scriptFailure(step, expectation) {
5930
+ if (step.error) return step.error;
5931
+ if (step.scriptEvent === "load") return `script.onload, aber ${expectation} \u2014 Ausfuehrung nicht belegt.`;
5932
+ if (step.scriptEvent === "error") return "script.onerror \u2014 Skript nicht geladen oder blockiert.";
5933
+ return "Kein Skript-Ereignis innerhalb der Wartezeit.";
5934
+ }
5935
+ async function loadFlowApp({
5936
+ bridge,
5937
+ environment,
5938
+ tokenSuffix,
5939
+ win = window,
5940
+ doc = document,
5941
+ digest = sha256Hex2,
5942
+ scriptTimeoutMs = FLOW_APP_SCRIPT_TIMEOUT_MS,
5943
+ onStep
5944
+ }) {
5945
+ const target = FLOW_APP_TARGETS[environment];
5946
+ const globals = win;
5947
+ const steps = [];
5948
+ const report = () => _optionalChain([onStep, 'optionalCall', _186 => _186(steps.map((step) => ({ ...step, cspViolations: [...step.cspViolations] })))]);
5949
+ const fail3 = (step, error) => {
5950
+ step.error = error;
5951
+ report();
5952
+ return { ok: false, steps, error: `${step.file}: ${error}` };
5953
+ };
5954
+ let css = "";
5955
+ for (const file of FLOW_APP_FILES) {
5956
+ const step = { file, response: null, chars: null, hash: null, scriptEvent: null, cspViolations: [], error: null };
5957
+ steps.push(step);
5958
+ report();
5959
+ step.response = await bridge.request(
5960
+ { target: target.bridgeTarget, method: "GET", path: `/flow-app/bundle/${file}`, tokenSuffix },
5961
+ { timeoutMs: FLOW_APP_REQUEST_TIMEOUT_MS }
5962
+ );
5963
+ if (!step.response.ok) {
5964
+ const status = step.response.status !== null ? `HTTP ${step.response.status} \xB7 ` : "";
5965
+ return fail3(step, `${status}${_optionalChain([step, 'access', _187 => _187.response, 'access', _188 => _188.error, 'optionalAccess', _189 => _189.code])}: ${_optionalChain([step, 'access', _190 => _190.response, 'access', _191 => _191.error, 'optionalAccess', _192 => _192.message])}`);
5966
+ }
5967
+ const loaded = readFlowAppFile(step.response.data, file);
5968
+ if (!loaded) return fail3(step, "Antwort ohne gueltige Datei.");
5969
+ step.chars = loaded.source.length;
5970
+ try {
5971
+ step.hash = await digest(loaded.source) === loaded.sha256 ? "ok" : "mismatch";
5972
+ } catch (e21) {
5973
+ step.hash = "unavailable";
5974
+ }
5975
+ if (step.hash === "mismatch") return fail3(step, "SHA-256 des empfangenen Quelltexts weicht ab \u2014 nicht ausgefuehrt.");
5976
+ if (file === "master.css") {
5977
+ css = loaded.source;
5978
+ report();
5979
+ continue;
5980
+ }
5981
+ if (file === "app.js") delete globals.FineArtApp;
5982
+ await runScriptBlob(loaded.source, doc, scriptTimeoutMs, step);
5983
+ if (file === "react-runtime.js") {
5984
+ const ReactDOM = globals.ReactDOM;
5985
+ if (!isRecord3(globals.React) || typeof _optionalChain([ReactDOM, 'optionalAccess', _193 => _193.createRoot]) !== "function") {
5986
+ return fail3(step, scriptFailure(step, "window.React/window.ReactDOM.createRoot fehlen"));
5987
+ }
5988
+ } else if (typeof globals.FineArtApp !== "function") {
5989
+ return fail3(step, scriptFailure(step, "window.FineArtApp fehlt"));
5990
+ }
5991
+ report();
5992
+ }
5993
+ return {
5994
+ ok: true,
5995
+ steps,
5996
+ css,
5997
+ runtime: {
5998
+ React: globals.React,
5999
+ ReactDOM: globals.ReactDOM,
6000
+ FineArtApp: globals.FineArtApp
6001
+ },
6002
+ backendUrl: target.backendUrl
6003
+ };
6004
+ }
6005
+
6006
+ // src/components/FlowFineArtApp.tsx
6007
+
6008
+ var FLOW_APP_STYLE_ID = "fa-flow-app-master-css";
6009
+ var BAR_HEIGHT = 32;
6010
+ function stepText(step) {
6011
+ const parts = [step.file];
6012
+ if (step.response) {
6013
+ parts.push(step.response.status !== null ? `HTTP ${step.response.status}` : "kein HTTP-Status");
6014
+ parts.push(`${_nullishCoalesce(step.response.transport, () => ( "kein Transport"))} \xB7 ${step.response.roundTripMs} ms`);
6015
+ } else {
6016
+ parts.push("l\xE4dt\u2026");
6017
+ }
6018
+ if (step.chars !== null) parts.push(`${step.chars} Zeichen`);
6019
+ if (step.hash === "ok") parts.push("Hash gepr\xFCft");
6020
+ if (step.hash === "unavailable") parts.push("Hash nicht pr\xFCfbar");
6021
+ if (step.scriptEvent) parts.push(`Skript ${step.scriptEvent}`);
6022
+ if (step.cspViolations.length > 0) parts.push(`CSP: ${step.cspViolations.join("; ")}`);
6023
+ if (step.error) parts.push(`FEHLER: ${step.error}`);
6024
+ return parts.join(" \xB7 ");
6025
+ }
6026
+ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) => {
6027
+ const bridge = _react.useMemo.call(void 0, () => _nullishCoalesce(client, () => ( createFlowBridgeClient({ appVersion }))), [client, appVersion]);
6028
+ const [connection, setConnection] = _react.useState.call(void 0, null);
6029
+ const [steps, setSteps] = _react.useState.call(void 0, []);
6030
+ const [load, setLoad] = _react.useState.call(void 0, null);
6031
+ const [renderError, setRenderError] = _react.useState.call(void 0, null);
6032
+ const appRootRef = _react.useRef.call(void 0, null);
6033
+ const tokenSuffix = hfTokenSuffix(hfToken);
6034
+ const target = FLOW_APP_TARGETS[environment];
6035
+ _react.useEffect.call(void 0, () => {
6036
+ if (!tokenSuffix) return void 0;
6037
+ let active = true;
6038
+ void (async () => {
6039
+ const connected = bridge.connect ? await bridge.connect(environment) : { ok: false, error: { code: "no-bridge", message: "Bridge-Client ohne connect." }, waitedMs: 0 };
6040
+ if (!active) return;
6041
+ setConnection(connected);
6042
+ if (!connected.ok) return;
6043
+ const result = await loadFlowApp({ bridge, environment, tokenSuffix, onStep: (next) => {
6044
+ if (active) setSteps(next);
6045
+ } });
6046
+ if (active) setLoad(result);
6047
+ })();
6048
+ return () => {
6049
+ active = false;
6050
+ };
6051
+ }, [bridge, environment, tokenSuffix]);
6052
+ _react.useEffect.call(void 0, () => {
6053
+ const container = appRootRef.current;
6054
+ if (!_optionalChain([load, 'optionalAccess', _194 => _194.ok]) || !container) return void 0;
6055
+ const style = document.createElement("style");
6056
+ style.id = FLOW_APP_STYLE_ID;
6057
+ style.textContent = load.css;
6058
+ document.head.appendChild(style);
6059
+ let root = null;
6060
+ try {
6061
+ root = load.runtime.ReactDOM.createRoot(container);
6062
+ root.render(load.runtime.React.createElement(load.runtime.FineArtApp, {
6063
+ customTabs: [],
6064
+ apiKey: null,
6065
+ backendUrl: load.backendUrl,
6066
+ transport: "flow-bridge"
6067
+ }));
6068
+ } catch (error) {
6069
+ setRenderError(error instanceof Error ? error.message : String(error));
6070
+ }
6071
+ return () => {
6072
+ _optionalChain([root, 'optionalAccess', _195 => _195.unmount, 'call', _196 => _196()]);
6073
+ style.remove();
6074
+ };
6075
+ }, [load]);
6076
+ const failed = !tokenSuffix || connection !== null && !connection.ok || load !== null && !load.ok || renderError !== null;
6077
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fixed inset-0 bg-[#0e0e0e] flex flex-col", "data-testid": "flow-fine-art-app", children: [
6078
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-3 px-3 text-[11px] font-mono text-white/60", style: { height: BAR_HEIGHT, borderBottom: "1px solid rgba(255,255,255,0.08)" }, children: [
6079
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", onClick: onClose, className: "font-bold text-white/80", children: "\u2190 FlowFA" }),
6080
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: `Fine-Art App \xB7 ${environment.toUpperCase()} \xB7 ${target.backendUrl}` })
6081
+ ] }),
6082
+ !_optionalChain([load, 'optionalAccess', _197 => _197.ok]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-1 p-4 text-[11px] font-mono break-all", "data-testid": "flow-fine-art-app-steps", children: [
6083
+ !tokenSuffix && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { role: "alert", style: { color: "#f87171" }, children: "Kein HF-Token in FlowFA gesetzt \u2014 ohne ihn kein Zugang zum MCP-Host." }),
6084
+ tokenSuffix && !connection && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "data-testid": "flow-fine-art-app-connect", style: { color: "#fbbf24" }, children: `Freigabe n\xF6tig: Extension-Popup \u201EFine-Art Flow Bridge\u201C \xF6ffnen (Zahl am Symbol) \u2192 \u201EFreigeben\u201C f\xFCr ${environment.toUpperCase()} (${target.backendUrl}).` }),
6085
+ connection && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "data-testid": "flow-fine-art-app-connect", style: { color: connection.ok ? "rgba(255,255,255,0.6)" : "#f87171" }, children: connection.ok ? `Freigegeben f\xFCr dieses Dokument \xB7 ${connection.server} \xB7 nach ${connection.waitedMs} ms` : `Keine Freigabe \u2014 ${connection.error.code}: ${connection.error.message}` }),
6086
+ connection && !connection.ok && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { role: "alert", className: "font-bold", style: { color: "#f87171" }, children: "App nicht gestartet \u2014 ohne Freigabe erreicht sie ihren Server nicht." }),
6087
+ steps.map((step) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { color: step.error ? "#f87171" : "rgba(255,255,255,0.6)" }, children: stepText(step) }, step.file)),
6088
+ load && !load.ok && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { role: "alert", className: "font-bold", style: { color: "#f87171" }, children: `App nicht gestartet \u2014 ${load.error}` })
6089
+ ] }),
6090
+ renderError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { role: "alert", className: "p-4 text-[11px] font-mono", style: { color: "#f87171" }, children: `App nicht gerendert \u2014 ${renderError}` }),
6091
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: appRootRef, className: "flex-1 overflow-auto", style: { display: _optionalChain([load, 'optionalAccess', _198 => _198.ok]) && !failed ? "block" : "none" } })
6092
+ ] });
6093
+ };
6094
+
5689
6095
  // src/lib/flowBootstrapTarget.ts
5690
6096
  var PROD_NAMESPACE = "app.art-by-rolands.de/";
5691
6097
  var DEV_NAMESPACE = "dev-app.art-by-rolands.de/";
@@ -5736,6 +6142,10 @@ function resolveBootstrapTarget(input) {
5736
6142
  environment: environmentForNamespace(namespace)
5737
6143
  };
5738
6144
  }
6145
+ function flowAppEnvironment(target, isDialogTarget, selectedNamespace) {
6146
+ if (isDialogTarget) return environmentForNamespace(normalizeSelectableNamespace(selectedNamespace));
6147
+ return target.ready ? target.environment : null;
6148
+ }
5739
6149
 
5740
6150
  // src/components/AvatarArchitectApp.tsx
5741
6151
 
@@ -5753,16 +6163,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5753
6163
  const [layoutChoice, setLayoutChoice] = _react.useState.call(void 0, () => {
5754
6164
  try {
5755
6165
  return localStorage.getItem("aa-layout") || null;
5756
- } catch (e21) {
6166
+ } catch (e22) {
5757
6167
  return null;
5758
6168
  }
5759
6169
  });
5760
6170
  const [hfToken, setHfToken] = _react.useState.call(void 0, initialHfToken || "");
6171
+ const [serverAppEnvironment, setServerAppEnvironment] = _react.useState.call(void 0, null);
5761
6172
  const [hfTokenInput, setHfTokenInput] = _react.useState.call(void 0, initialHfToken || "");
5762
6173
  const [hfNamespaceLocal, setHfNamespaceLocal] = _react.useState.call(void 0, () => {
5763
6174
  try {
5764
6175
  return normalizeSelectableNamespace(localStorage.getItem("aa-hf-namespace"));
5765
- } catch (e22) {
6176
+ } catch (e23) {
5766
6177
  return DEFAULT_NAMESPACE;
5767
6178
  }
5768
6179
  });
@@ -5865,7 +6276,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5865
6276
  const startApp = (choice) => {
5866
6277
  try {
5867
6278
  localStorage.setItem("aa-layout", choice);
5868
- } catch (e23) {
6279
+ } catch (e24) {
5869
6280
  }
5870
6281
  setLayoutChoice(choice);
5871
6282
  setTargetConfirmed(true);
@@ -5886,7 +6297,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5886
6297
  const loadThumbnailsForEntries = _react.useCallback.call(void 0, async (entries) => {
5887
6298
  await loadThumbnailsSequentially(entries, {
5888
6299
  inFlight: hfInFlightRef.current,
5889
- isAlreadyLoaded: (entry) => !!_optionalChain([galleryItemsRef, 'access', _158 => _158.current, 'access', _159 => _159.find, 'call', _160 => _160((g) => g.id === entry.id), 'optionalAccess', _161 => _161.base64]),
6300
+ isAlreadyLoaded: (entry) => !!_optionalChain([galleryItemsRef, 'access', _199 => _199.current, 'access', _200 => _200.find, 'call', _201 => _201((g) => g.id === entry.id), 'optionalAccess', _202 => _202.base64]),
5890
6301
  isKnownMissing: (entry) => hfImageNotFoundRef.current.has(entry.id),
5891
6302
  loadImage: (entry) => _chunkVSHSZEGVjs.hfLoadImageAsBase64.call(void 0, entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb),
5892
6303
  onLoaded: (entry, b64) => {
@@ -5905,7 +6316,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5905
6316
  }, [hfToken, effectiveNamespace]);
5906
6317
  _react.useEffect.call(void 0, () => {
5907
6318
  if (!hfState) return;
5908
- if (_optionalChain([hfState, 'access', _162 => _162.tags, 'optionalAccess', _163 => _163.by_category])) setWorkspaceTags(hfState.tags);
6319
+ if (_optionalChain([hfState, 'access', _203 => _203.tags, 'optionalAccess', _204 => _204.by_category])) setWorkspaceTags(hfState.tags);
5909
6320
  const hfIds = new Set(hfState.metadata.map((m) => m.id));
5910
6321
  const skeletons = hfState.metadata.map((m) => ({
5911
6322
  id: m.id,
@@ -5951,7 +6362,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5951
6362
  try {
5952
6363
  const v = parseInt(localStorage.getItem("aa-image-count") || "", 10);
5953
6364
  return v >= 1 && v <= 8 ? v : 4;
5954
- } catch (e24) {
6365
+ } catch (e25) {
5955
6366
  return 4;
5956
6367
  }
5957
6368
  });
@@ -5960,7 +6371,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5960
6371
  setImageCount(n);
5961
6372
  try {
5962
6373
  localStorage.setItem("aa-image-count", String(n));
5963
- } catch (e25) {
6374
+ } catch (e26) {
5964
6375
  }
5965
6376
  };
5966
6377
  const imageCountOptions = [
@@ -5974,14 +6385,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5974
6385
  const [leftPanelWidth, setLeftPanelWidth] = _react.useState.call(void 0, () => {
5975
6386
  try {
5976
6387
  return parseInt(localStorage.getItem("aa-left-width") || "260", 10);
5977
- } catch (e26) {
6388
+ } catch (e27) {
5978
6389
  return 260;
5979
6390
  }
5980
6391
  });
5981
6392
  const [rightPanelWidth, setRightPanelWidth] = _react.useState.call(void 0, () => {
5982
6393
  try {
5983
6394
  return parseInt(localStorage.getItem("aa-right-width") || "320", 10);
5984
- } catch (e27) {
6395
+ } catch (e28) {
5985
6396
  return 320;
5986
6397
  }
5987
6398
  });
@@ -5990,7 +6401,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5990
6401
  const [highContrast, setHighContrast] = _react.useState.call(void 0, () => {
5991
6402
  try {
5992
6403
  return localStorage.getItem("aa-contrast") === "high";
5993
- } catch (e28) {
6404
+ } catch (e29) {
5994
6405
  return false;
5995
6406
  }
5996
6407
  });
@@ -6003,14 +6414,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6003
6414
  const [zoomOffset, setZoomOffset] = _react.useState.call(void 0, { x: 0, y: 0 });
6004
6415
  const { historyVisible, galleryVisible } = computePrefetchVisibility({
6005
6416
  layoutChoice,
6006
- appShellVisible: !showStart && !requireWorkspaceSelection && !(isFullscreen && !!_optionalChain([currentResult, 'optionalAccess', _164 => _164.base64])),
6417
+ appShellVisible: !showStart && !requireWorkspaceSelection && !(isFullscreen && !!_optionalChain([currentResult, 'optionalAccess', _205 => _205.base64])),
6007
6418
  mobileTab,
6008
6419
  middlePanel,
6009
6420
  activeTab,
6010
6421
  isRightCollapsed
6011
6422
  });
6012
6423
  useThumbnailPrefetch({
6013
- metadata: _optionalChain([hfState, 'optionalAccess', _165 => _165.metadata]),
6424
+ metadata: _optionalChain([hfState, 'optionalAccess', _206 => _206.metadata]),
6014
6425
  historyVisible,
6015
6426
  galleryVisible,
6016
6427
  historyVisibleCount,
@@ -6066,12 +6477,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6066
6477
  setHighContrast(next);
6067
6478
  try {
6068
6479
  localStorage.setItem("aa-contrast", next ? "high" : "low");
6069
- } catch (e29) {
6480
+ } catch (e30) {
6070
6481
  }
6071
6482
  };
6072
6483
  const handleSelectReference = async () => {
6073
6484
  const media = await onSelectMedia();
6074
- if (!_optionalChain([media, 'optionalAccess', _166 => _166.length])) return;
6485
+ if (!_optionalChain([media, 'optionalAccess', _207 => _207.length])) return;
6075
6486
  const first = media[0];
6076
6487
  if (first.mediaId) {
6077
6488
  setActiveReferenceId(first.mediaId);
@@ -6094,7 +6505,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6094
6505
  generateImage: onGenerateImage,
6095
6506
  saveResult: async (item) => {
6096
6507
  const frame = item.frames[0];
6097
- if (_optionalChain([frame, 'optionalAccess', _167 => _167.base64])) {
6508
+ if (_optionalChain([frame, 'optionalAccess', _208 => _208.base64])) {
6098
6509
  const gen = frameToGeneration(frame, item);
6099
6510
  setGalleryItems((prev) => [gen, ...prev]);
6100
6511
  setHistory((prev) => [gen, ...prev]);
@@ -6112,7 +6523,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6112
6523
  setLeftPanelWidth(w);
6113
6524
  try {
6114
6525
  localStorage.setItem("aa-left-width", String(w));
6115
- } catch (e30) {
6526
+ } catch (e31) {
6116
6527
  }
6117
6528
  };
6118
6529
  const onUp = () => {
@@ -6131,7 +6542,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6131
6542
  setRightPanelWidth(w);
6132
6543
  try {
6133
6544
  localStorage.setItem("aa-right-width", String(w));
6134
- } catch (e31) {
6545
+ } catch (e32) {
6135
6546
  }
6136
6547
  };
6137
6548
  const onUp = () => {
@@ -6162,7 +6573,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6162
6573
  setIsScanningImage(false);
6163
6574
  }
6164
6575
  };
6165
- const currentIndex = _react.useMemo.call(void 0, () => history.findIndex((h) => h.id === _optionalChain([currentResult, 'optionalAccess', _168 => _168.id])), [history, currentResult]);
6576
+ const currentIndex = _react.useMemo.call(void 0, () => history.findIndex((h) => h.id === _optionalChain([currentResult, 'optionalAccess', _209 => _209.id])), [history, currentResult]);
6166
6577
  const goToPrev = _react.useCallback.call(void 0, () => {
6167
6578
  if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
6168
6579
  }, [currentIndex, history]);
@@ -6176,7 +6587,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6176
6587
  _chunkVSHSZEGVjs.hfLoadImageAsBase64.call(void 0, g.id, hfToken, effectiveNamespace, g.filename, void 0, g.mimeType, false).then((b64) => {
6177
6588
  if (!b64) return;
6178
6589
  const full = `data:${g.mimeType || "image/jpeg"};base64,${b64}`;
6179
- setCurrentResult((prev) => _optionalChain([prev, 'optionalAccess', _169 => _169.id]) === g.id ? { ...prev, fullBase64: full } : prev);
6590
+ setCurrentResult((prev) => _optionalChain([prev, 'optionalAccess', _210 => _210.id]) === g.id ? { ...prev, fullBase64: full } : prev);
6180
6591
  setGalleryItems((prev) => prev.map((item) => item.id === g.id ? { ...item, fullBase64: full } : item));
6181
6592
  }).catch(() => {
6182
6593
  });
@@ -6192,13 +6603,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6192
6603
  }
6193
6604
  }, [hfToken, effectiveNamespace, hfWriteEvent]);
6194
6605
  const currentGroup = _react.useMemo.call(void 0, () => {
6195
- if (!_optionalChain([currentResult, 'optionalAccess', _170 => _170.prompt])) return [];
6606
+ if (!_optionalChain([currentResult, 'optionalAccess', _211 => _211.prompt])) return [];
6196
6607
  const groups = groupByPrompt(galleryItems.filter((g) => g.status === "done" && !!g.base64));
6197
6608
  const group = groups.find((gr) => gr.prompt === currentResult.prompt);
6198
6609
  return group ? group.items : [];
6199
- }, [galleryItems, _optionalChain([currentResult, 'optionalAccess', _171 => _171.prompt])]);
6610
+ }, [galleryItems, _optionalChain([currentResult, 'optionalAccess', _212 => _212.prompt])]);
6200
6611
  _react.useEffect.call(void 0, () => {
6201
- if (!_optionalChain([currentResult, 'optionalAccess', _172 => _172.prompt]) || !hfToken || !effectiveNamespace || !hfState) return;
6612
+ if (!_optionalChain([currentResult, 'optionalAccess', _213 => _213.prompt]) || !hfToken || !effectiveNamespace || !hfState) return;
6202
6613
  const siblings = galleryItemsRef.current.filter(
6203
6614
  (g) => g.prompt === currentResult.prompt && !g.base64 && !hfImageNotFoundRef.current.has(g.id)
6204
6615
  );
@@ -6216,12 +6627,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6216
6627
  const prefix = `data:${meta.mimeType || "image/jpeg"};base64,`;
6217
6628
  setGalleryItems((prev) => prev.map((g) => g.id === sib.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
6218
6629
  setHistory((prev) => prev.map((g) => g.id === sib.id && !g.base64 ? { ...g, base64: prefix + b64 } : g));
6219
- } catch (e32) {
6630
+ } catch (e33) {
6220
6631
  hfImageNotFoundRef.current.set(sib.id, Date.now());
6221
6632
  }
6222
6633
  }
6223
6634
  })();
6224
- }, [_optionalChain([currentResult, 'optionalAccess', _173 => _173.id]), _optionalChain([currentResult, 'optionalAccess', _174 => _174.prompt])]);
6635
+ }, [_optionalChain([currentResult, 'optionalAccess', _214 => _214.id]), _optionalChain([currentResult, 'optionalAccess', _215 => _215.prompt])]);
6225
6636
  const hcStyle = highContrast ? { filter: "brightness(1.6) contrast(1.05)" } : void 0;
6226
6637
  const runningBadge = activeGenerationsCount > 0 ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6227
6638
  "div",
@@ -6302,7 +6713,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6302
6713
  const errorGen = { ...newGen, status: "error", error: { message: err.message || "Unbekannter Fehler", details: err.toString() } };
6303
6714
  setHistory((prev) => prev.map((g) => g.id === genId ? errorGen : g));
6304
6715
  setGalleryItems((prev) => prev.filter((g) => g.id !== genId));
6305
- if (!options.silent || _optionalChain([currentResult, 'optionalAccess', _175 => _175.id]) === genId) setCurrentResult(errorGen);
6716
+ if (!options.silent || _optionalChain([currentResult, 'optionalAccess', _216 => _216.id]) === genId) setCurrentResult(errorGen);
6306
6717
  } finally {
6307
6718
  setActiveGenerationsCount((prev) => Math.max(0, prev - 1));
6308
6719
  }
@@ -6358,7 +6769,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6358
6769
  setActivePrompt(prompt);
6359
6770
  setFocusedNodeId(nodeId);
6360
6771
  if (autoGenerate) handleGenerateImage(prompt, void 0, nodeId);
6361
- } catch (e33) {
6772
+ } catch (e34) {
6362
6773
  setActivePrompt("Synthese-Fehler");
6363
6774
  } finally {
6364
6775
  setIsSynthesizing(false);
@@ -6431,14 +6842,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6431
6842
  const { prompt, feedback } = parsePromptResponse(raw);
6432
6843
  setActivePrompt(prompt);
6433
6844
  setPromptFeedback(feedback);
6434
- } catch (e34) {
6845
+ } catch (e35) {
6435
6846
  setActivePrompt("Synthese-Fehler");
6436
6847
  } finally {
6437
6848
  setIsPromptTabGenerating(false);
6438
6849
  }
6439
6850
  };
6440
6851
  const handleDownloadSingle = async () => {
6441
- if (!_optionalChain([currentResult, 'optionalAccess', _176 => _176.base64])) return;
6852
+ if (!_optionalChain([currentResult, 'optionalAccess', _217 => _217.base64])) return;
6442
6853
  try {
6443
6854
  const downloadSrc = currentResult.fullBase64 || currentResult.base64;
6444
6855
  const base64Data = downloadSrc.split(",")[1];
@@ -6454,9 +6865,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6454
6865
  const reader = new FileReader();
6455
6866
  reader.onload = (ev) => {
6456
6867
  try {
6457
- const root = JSON.parse(_optionalChain([ev, 'access', _177 => _177.target, 'optionalAccess', _178 => _178.result]));
6868
+ const root = JSON.parse(_optionalChain([ev, 'access', _218 => _218.target, 'optionalAccess', _219 => _219.result]));
6458
6869
  const rawTags = root.tags || root;
6459
- if (!_optionalChain([rawTags, 'optionalAccess', _179 => _179.by_category])) return;
6870
+ if (!_optionalChain([rawTags, 'optionalAccess', _220 => _220.by_category])) return;
6460
6871
  const filtered = {};
6461
6872
  const EXCLUDED2 = ["pdf-export", "book.micro-edit-rules"];
6462
6873
  Object.entries(rawTags.by_category).forEach(([cat, items]) => {
@@ -6473,7 +6884,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6473
6884
  };
6474
6885
  const handleHfInitialSync = async (onProgress) => {
6475
6886
  if (!hfToken || !effectiveNamespace) return;
6476
- const existingIds = new Set((_optionalChain([hfState, 'optionalAccess', _180 => _180.metadata]) || []).map((m) => m.id));
6887
+ const existingIds = new Set((_optionalChain([hfState, 'optionalAccess', _221 => _221.metadata]) || []).map((m) => m.id));
6477
6888
  const gens = galleryItems.filter((g) => g.base64 && g.status === "done" && !existingIds.has(g.id));
6478
6889
  const total = gens.length;
6479
6890
  onProgress(0, total);
@@ -6499,7 +6910,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6499
6910
  }
6500
6911
  };
6501
6912
  const mergeWorkspaceTags = (local, remote) => {
6502
- if (!_optionalChain([remote, 'optionalAccess', _181 => _181.by_category])) return local;
6913
+ if (!_optionalChain([remote, 'optionalAccess', _222 => _222.by_category])) return local;
6503
6914
  const merged = {};
6504
6915
  const allCategories = /* @__PURE__ */ new Set([...Object.keys(local.by_category), ...Object.keys(remote.by_category)]);
6505
6916
  for (const cat of allCategories) {
@@ -6509,7 +6920,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6509
6920
  const localValues = new Set(localTags.map((t) => t.value));
6510
6921
  const mergedLocal = localTags.map((t) => {
6511
6922
  const remote2 = remoteMap.get(t.value);
6512
- return _optionalChain([remote2, 'optionalAccess', _182 => _182.is_deleted]) ? { ...t, is_deleted: true } : t;
6923
+ return _optionalChain([remote2, 'optionalAccess', _223 => _223.is_deleted]) ? { ...t, is_deleted: true } : t;
6513
6924
  });
6514
6925
  const onlyInRemote = remoteTags.filter((t) => !localValues.has(t.value));
6515
6926
  merged[cat] = [...mergedLocal, ...onlyInRemote];
@@ -6517,7 +6928,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6517
6928
  const all = Object.entries(merged).flatMap(([cat, tags]) => tags.map((t) => ({ ...t, category: cat })));
6518
6929
  return { by_category: merged, all };
6519
6930
  };
6520
- if (isFullscreen && _optionalChain([currentResult, 'optionalAccess', _183 => _183.base64])) {
6931
+ if (isFullscreen && _optionalChain([currentResult, 'optionalAccess', _224 => _224.base64])) {
6521
6932
  const fsRaw = currentResult.fullBase64 || currentResult.base64;
6522
6933
  const fsBase64 = fsRaw.startsWith("data:") ? fsRaw : `data:image/png;base64,${fsRaw}`;
6523
6934
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -6568,7 +6979,11 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6568
6979
  }
6569
6980
  );
6570
6981
  }
6982
+ if (serverAppEnvironment) {
6983
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FlowFineArtApp, { environment: serverAppEnvironment, hfToken, appVersion: version, onClose: () => setServerAppEnvironment(null) });
6984
+ }
6571
6985
  if (showStart) {
6986
+ const serverAppTarget = flowAppEnvironment(bootstrapTarget, isDialogTarget, hfNamespaceLocal);
6572
6987
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "fixed inset-0 bg-[#0e0e0e] flex flex-col items-center justify-center p-6", style: { gap: 28, ...hcStyle }, children: [
6573
6988
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-1", children: [
6574
6989
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-white/15 text-[44px]", children: "palette" }),
@@ -6631,7 +7046,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6631
7046
  setHfNamespaceLocal(ns);
6632
7047
  try {
6633
7048
  localStorage.setItem("aa-hf-namespace", ns);
6634
- } catch (e35) {
7049
+ } catch (e36) {
6635
7050
  }
6636
7051
  },
6637
7052
  className: "px-3 py-1 rounded-lg text-[11px] font-bold transition-colors",
@@ -6668,7 +7083,20 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6668
7083
  layoutChoice === "mobile-desktop" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-white/20 text-[9px] text-center", children: "Mobil-Layout skaliert f\xFCr Desktop-Modus" }),
6669
7084
  layoutChoice === "tablet-landscape" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-white/20 text-[9px] text-center", children: "2-Spalten-Layout f\xFCr Landscape-Tablet im Desktop-Mode" })
6670
7085
  ] }),
6671
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FlowBridgePanel, { appVersion: version })
7086
+ serverAppTarget && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7087
+ "button",
7088
+ {
7089
+ type: "button",
7090
+ onClick: () => setServerAppEnvironment(serverAppTarget),
7091
+ className: "flex items-center justify-center gap-2 w-full max-w-[280px] py-3 rounded-2xl border text-[11px] font-bold",
7092
+ style: { borderColor: "rgba(255,255,255,0.08)", color: "rgba(255,255,255,0.6)" },
7093
+ children: [
7094
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[20px]", children: "web" }),
7095
+ `Fine-Art App (Server) \xB7 ${serverAppTarget.toUpperCase()}`
7096
+ ]
7097
+ }
7098
+ ),
7099
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FlowBridgePanel, { appVersion: version, hfToken })
6672
7100
  ] });
6673
7101
  }
6674
7102
  if (requireWorkspaceSelection) {
@@ -6732,7 +7160,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6732
7160
  }, children: [
6733
7161
  mobileTab === "labs" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex flex-col flex-1 min-h-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LabsTab, { services: labServices, onResult: (item) => {
6734
7162
  const frame = item.frames[0];
6735
- if (_optionalChain([frame, 'optionalAccess', _184 => _184.base64])) {
7163
+ if (_optionalChain([frame, 'optionalAccess', _225 => _225.base64])) {
6736
7164
  setCurrentResult(frameToGeneration(frame, item));
6737
7165
  setMobileTab("stage");
6738
7166
  }
@@ -6756,7 +7184,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6756
7184
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
6757
7185
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
6758
7186
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1" }),
6759
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _185 => _185.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7187
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _226 => _226.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
6760
7188
  runningBadge,
6761
7189
  activeReferenceThumbnail ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 rounded-lg border border-white/20 bg-white/5 overflow-hidden mr-2", style: { height: 28 }, children: [
6762
7190
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
@@ -6807,21 +7235,21 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6807
7235
  setTouchStartX(null);
6808
7236
  },
6809
7237
  children: [
6810
- _optionalChain([currentResult, 'optionalAccess', _186 => _186.status]) === "processing" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-3 opacity-40", children: [
7238
+ _optionalChain([currentResult, 'optionalAccess', _227 => _227.status]) === "processing" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-3 opacity-40", children: [
6811
7239
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
6812
7240
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[11px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
6813
7241
  ] }),
6814
- _optionalChain([currentResult, 'optionalAccess', _187 => _187.status]) === "error" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
7242
+ _optionalChain([currentResult, 'optionalAccess', _228 => _228.status]) === "error" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
6815
7243
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
6816
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-white/50 text-[13px]", children: _optionalChain([currentResult, 'access', _188 => _188.error, 'optionalAccess', _189 => _189.message]) }),
7244
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-white/50 text-[13px]", children: _optionalChain([currentResult, 'access', _229 => _229.error, 'optionalAccess', _230 => _230.message]) }),
6817
7245
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: () => handleGenerateImage(currentResult.prompt), className: "px-4 py-2 rounded-lg border border-white/20 text-[13px] text-white/70 active:bg-white/10", children: "Erneut versuchen" })
6818
7246
  ] }),
6819
- _optionalChain([currentResult, 'optionalAccess', _190 => _190.status]) === "done" && currentResult.base64 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: currentResult.fullBase64 || currentResult.base64, className: "w-full h-full object-contain" }),
7247
+ _optionalChain([currentResult, 'optionalAccess', _231 => _231.status]) === "done" && currentResult.base64 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: currentResult.fullBase64 || currentResult.base64, className: "w-full h-full object-contain" }),
6820
7248
  !currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
6821
7249
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[64px]", children: "palette" }),
6822
7250
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[11px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
6823
7251
  ] }),
6824
- _optionalChain([currentResult, 'optionalAccess', _191 => _191.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: openFullscreen, className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center rounded-full bg-black/60 border border-white/10 z-10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[18px]", children: "fullscreen" }) }),
7252
+ _optionalChain([currentResult, 'optionalAccess', _232 => _232.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: openFullscreen, className: "absolute top-2 right-2 w-8 h-8 flex items-center justify-center rounded-full bg-black/60 border border-white/10 z-10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[18px]", children: "fullscreen" }) }),
6825
7253
  history.length > 1 && currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
6826
7254
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: goToPrev, disabled: currentIndex <= 0, className: "absolute left-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[22px]", children: "chevron_left" }) }),
6827
7255
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, className: "absolute right-2 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center rounded-full bg-black/60 border border-white/10 disabled:opacity-0 transition-opacity", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[22px]", children: "chevron_right" }) }),
@@ -6834,7 +7262,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6834
7262
  ]
6835
7263
  }
6836
7264
  ),
6837
- _optionalChain([currentResult, 'optionalAccess', _192 => _192.status]) === "done" && currentGroup.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-2 flex gap-1.5 overflow-x-auto pb-1", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { position: "relative", flexShrink: 0 }, children: [
7265
+ _optionalChain([currentResult, 'optionalAccess', _233 => _233.status]) === "done" && currentGroup.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "mt-2 flex gap-1.5 overflow-x-auto pb-1", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { position: "relative", flexShrink: 0 }, children: [
6838
7266
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6839
7267
  "div",
6840
7268
  {
@@ -6877,7 +7305,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6877
7305
  }
6878
7306
  )
6879
7307
  ] }, item.id)) }),
6880
- _optionalChain([currentResult, 'optionalAccess', _193 => _193.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2 mt-3", children: [
7308
+ _optionalChain([currentResult, 'optionalAccess', _234 => _234.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2 mt-3", children: [
6881
7309
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { onClick: () => setActivePrompt(currentResult.prompt || ""), className: "flex-1 flex items-center justify-center gap-1.5 rounded-xl border border-white/10 bg-white/5 active:bg-white/10 transition-colors", style: { height: 44 }, children: [
6882
7310
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
6883
7311
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[12px] text-white/60", children: "Prompt" })
@@ -6899,14 +7327,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6899
7327
  hfToken && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: () => refreshHF(), disabled: isHfRefreshing, className: "w-12 flex items-center justify-center text-white/20 active:text-white transition-colors disabled:opacity-30", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `material-symbols-outlined text-[20px]${isHfRefreshing ? " animate-spin" : ""}`, children: "sync" }) })
6900
7328
  ] }),
6901
7329
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 overflow-hidden relative", children: [
6902
- activeTab === "history" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _194 => _194.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
7330
+ activeTab === "history" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _235 => _235.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
6903
7331
  activeTab === "gallery" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6904
7332
  MediaLibrary,
6905
7333
  {
6906
7334
  items: galleryItems,
6907
7335
  onImport: async () => {
6908
7336
  const media = await onSelectMedia();
6909
- if (!_optionalChain([media, 'optionalAccess', _195 => _195.length])) return;
7337
+ if (!_optionalChain([media, 'optionalAccess', _236 => _236.length])) return;
6910
7338
  setGalleryItems((prev) => [...media.map((m) => ({ id: crypto.randomUUID(), nodeId: "1", base64: `data:${m.mimeType};base64,${m.base64}`, mediaId: m.mediaId, prompt: m.name || "Importiert", timestamp: Date.now(), status: "done", tags: [], type: "import" })), ...prev]);
6911
7339
  },
6912
7340
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
@@ -7054,7 +7482,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7054
7482
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CompactDropdown, { value: selectedModel, onChange: setSelectedModel, options: [{ value: "\u{1F34C} Nano Banana Pro", label: "\u{1F34C} Nano Banana Pro" }, { value: "\u{1F34C} Nano Banana 2", label: "\u{1F34C} Nano Banana 2" }, { value: "Imagen 4", label: "Imagen 4" }] }),
7055
7483
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
7056
7484
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { flex: 1 } }),
7057
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _196 => _196.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7485
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _237 => _237.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7058
7486
  runningBadge,
7059
7487
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: toggleContrast, style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: highContrast ? "light_mode" : "dark_mode" }) }),
7060
7488
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: () => setShowStart(true), style: { color: "rgba(255,255,255,0.2)", background: "none", border: "none", cursor: "pointer", padding: 4, lineHeight: 0 }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "apps" }) })
@@ -7083,7 +7511,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7083
7511
  ]
7084
7512
  }
7085
7513
  ) }),
7086
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _197 => _197.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }) })
7514
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { flex: 1, overflow: "hidden", position: "relative" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _238 => _238.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }) })
7087
7515
  ] }),
7088
7516
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
7089
7517
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -7099,21 +7527,21 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7099
7527
  setTouchStartX(null);
7100
7528
  },
7101
7529
  children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { height: "100%", width: "100%", borderRadius: 20, border: "1px solid rgba(255,255,255,0.05)", background: "rgba(0,0,0,0.4)", position: "relative", overflow: "hidden", display: "flex", alignItems: "center", justifyContent: "center" }, children: [
7102
- _optionalChain([currentResult, 'optionalAccess', _198 => _198.status]) === "processing" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, opacity: 0.4 }, children: [
7530
+ _optionalChain([currentResult, 'optionalAccess', _239 => _239.status]) === "processing" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, opacity: 0.4 }, children: [
7103
7531
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 36 }, children: "hourglass_top" }),
7104
7532
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { fontSize: 10, color: "rgba(255,255,255,0.6)", textTransform: "uppercase", fontWeight: "bold", letterSpacing: "0.15em" }, children: "Erstelle Bild..." })
7105
7533
  ] }),
7106
- _optionalChain([currentResult, 'optionalAccess', _199 => _199.status]) === "error" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
7534
+ _optionalChain([currentResult, 'optionalAccess', _240 => _240.status]) === "error" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
7107
7535
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
7108
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", margin: 0 }, children: _optionalChain([currentResult, 'access', _200 => _200.error, 'optionalAccess', _201 => _201.message]) }),
7536
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", margin: 0 }, children: _optionalChain([currentResult, 'access', _241 => _241.error, 'optionalAccess', _242 => _242.message]) }),
7109
7537
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: () => handleGenerateImage(currentResult.prompt), style: { padding: "8px 16px", borderRadius: 8, border: "1px solid rgba(255,255,255,0.2)", fontSize: 11, color: "rgba(255,255,255,0.7)", background: "none", cursor: "pointer", fontFamily: "inherit" }, children: "Erneut versuchen" })
7110
7538
  ] }),
7111
- _optionalChain([currentResult, 'optionalAccess', _202 => _202.status]) === "done" && currentResult.base64 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: currentResult.fullBase64 || currentResult.base64, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }),
7539
+ _optionalChain([currentResult, 'optionalAccess', _243 => _243.status]) === "done" && currentResult.base64 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: currentResult.fullBase64 || currentResult.base64, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }),
7112
7540
  !currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 8, opacity: 0.1 }, children: [
7113
7541
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 64 }, children: "palette" }),
7114
7542
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { fontSize: 11, fontWeight: "bold", textTransform: "uppercase", letterSpacing: "0.2em" }, children: "Avatar Architect" })
7115
7543
  ] }),
7116
- _optionalChain([currentResult, 'optionalAccess', _203 => _203.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: openFullscreen, style: { position: "absolute", top: 8, right: 8, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "fullscreen" }) }),
7544
+ _optionalChain([currentResult, 'optionalAccess', _244 => _244.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: openFullscreen, style: { position: "absolute", top: 8, right: 8, width: 32, height: 32, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 18 }, children: "fullscreen" }) }),
7117
7545
  history.length > 1 && currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
7118
7546
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: goToPrev, disabled: currentIndex <= 0, style: { position: "absolute", left: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex <= 0 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_left" }) }),
7119
7547
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: goToNext, disabled: currentIndex >= history.length - 1, style: { position: "absolute", right: 8, top: "50%", transform: "translateY(-50%)", width: 36, height: 36, display: "flex", alignItems: "center", justifyContent: "center", borderRadius: "50%", background: "rgba(0,0,0,0.6)", border: "1px solid rgba(255,255,255,0.1)", cursor: "pointer", color: "#fff", opacity: currentIndex >= history.length - 1 ? 0 : 1, transition: "opacity 0.2s" }, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 20 }, children: "chevron_right" }) }),
@@ -7126,7 +7554,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7126
7554
  ] })
7127
7555
  }
7128
7556
  ),
7129
- _optionalChain([currentResult, 'optionalAccess', _204 => _204.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { padding: "0 16px 16px", display: "flex", gap: 8, flexShrink: 0 }, children: [
7557
+ _optionalChain([currentResult, 'optionalAccess', _245 => _245.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { padding: "0 16px 16px", display: "flex", gap: 8, flexShrink: 0 }, children: [
7130
7558
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { onClick: () => setActivePrompt(currentResult.prompt || ""), style: { flex: 1, height: 40, display: "flex", alignItems: "center", justifyContent: "center", gap: 6, borderRadius: 10, border: "1px solid rgba(255,255,255,0.1)", background: "rgba(255,255,255,0.05)", color: "rgba(255,255,255,0.6)", fontSize: 11, cursor: "pointer", fontFamily: "inherit" }, children: [
7131
7559
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
7132
7560
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Prompt" })
@@ -7248,7 +7676,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7248
7676
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Ref" })
7249
7677
  ] }),
7250
7678
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { onClick: () => setIsPromptCollapsed(!isPromptCollapsed), className: "text-white/40 hover:text-white transition-colors", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", children: isPromptCollapsed ? "expand_more" : "expand_less" }) }),
7251
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _205 => _205.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7679
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _246 => _246.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7252
7680
  runningBadge,
7253
7681
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PillButton, { variant: "solid", icon: "bolt", disabled: !activePrompt.trim(), onClick: () => handleGenerateBatch(), children: "Generieren" })
7254
7682
  ] })
@@ -7260,7 +7688,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7260
7688
  ] }) }),
7261
7689
  middlePanel === "szenen" ? szenenPane : middlePanel === "labs" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 overflow-hidden", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LabsTab, { services: labServices, onResult: (item) => {
7262
7690
  const frame = item.frames[0];
7263
- if (_optionalChain([frame, 'optionalAccess', _206 => _206.base64])) setCurrentResult(frameToGeneration(frame, item));
7691
+ if (_optionalChain([frame, 'optionalAccess', _247 => _247.base64])) setCurrentResult(frameToGeneration(frame, item));
7264
7692
  } }) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 overflow-hidden flex flex-col", children: [
7265
7693
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1 p-6 overflow-hidden flex items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full w-full max-w-4xl aspect-square rounded-3xl border border-white/5 bg-black/40 relative overflow-hidden flex items-center justify-center group shadow-2xl", children: currentResult ? currentResult.status === "processing" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-4 opacity-40", children: [
7266
7694
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
@@ -7269,7 +7697,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7269
7697
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-16 h-16 rounded-full bg-red-500/10 flex items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-red-500 text-[32px]", children: "warning" }) }),
7270
7698
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2", children: [
7271
7699
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
7272
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-white/60 text-[12px] leading-relaxed", children: _optionalChain([currentResult, 'access', _207 => _207.error, 'optionalAccess', _208 => _208.message]) })
7700
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-white/60 text-[12px] leading-relaxed", children: _optionalChain([currentResult, 'access', _248 => _248.error, 'optionalAccess', _249 => _249.message]) })
7273
7701
  ] }),
7274
7702
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
7275
7703
  ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "h-full w-full relative flex items-center justify-center", children: [
@@ -7283,7 +7711,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7283
7711
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
7284
7712
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
7285
7713
  ] }) }) }),
7286
- _optionalChain([currentResult, 'optionalAccess', _209 => _209.status]) === "done" && currentGroup.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-6 pb-4 shrink-0 flex gap-2 overflow-x-auto", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { position: "relative", flexShrink: 0 }, children: [
7714
+ _optionalChain([currentResult, 'optionalAccess', _250 => _250.status]) === "done" && currentGroup.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "px-6 pb-4 shrink-0 flex gap-2 overflow-x-auto", style: { scrollbarWidth: "none" }, children: currentGroup.map((item) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { position: "relative", flexShrink: 0 }, children: [
7287
7715
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7288
7716
  "div",
7289
7717
  {
@@ -7364,14 +7792,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7364
7792
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
7365
7793
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
7366
7794
  ] }) }),
7367
- activeTab === "history" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _210 => _210.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
7795
+ activeTab === "history" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _251 => _251.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
7368
7796
  activeTab === "gallery" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7369
7797
  MediaLibrary,
7370
7798
  {
7371
7799
  items: galleryItems,
7372
7800
  onImport: async () => {
7373
7801
  const media = await onSelectMedia();
7374
- if (!_optionalChain([media, 'optionalAccess', _211 => _211.length])) return;
7802
+ if (!_optionalChain([media, 'optionalAccess', _252 => _252.length])) return;
7375
7803
  setGalleryItems((prev) => [...media.map((m) => ({ id: crypto.randomUUID(), nodeId: "1", base64: `data:${m.mimeType};base64,${m.base64}`, mediaId: m.mediaId, prompt: m.name || "Importiert", timestamp: Date.now(), status: "done", tags: [], type: "import" })), ...prev]);
7376
7804
  },
7377
7805
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
@@ -7527,7 +7955,7 @@ function createFaStore({ contracts, descriptors, persistence, workspaceId }) {
7527
7955
  };
7528
7956
  };
7529
7957
  const applyWriteResult = (sliceId, result, savedData, signal) => {
7530
- if (_optionalChain([signal, 'optionalAccess', _212 => _212.aborted])) {
7958
+ if (_optionalChain([signal, 'optionalAccess', _253 => _253.aborted])) {
7531
7959
  patchMeta(sliceId, { saveState: "idle" });
7532
7960
  return result;
7533
7961
  }
@@ -7555,8 +7983,8 @@ function createFaStore({ contracts, descriptors, persistence, workspaceId }) {
7555
7983
  const requestId = _nullishCoalesce(externalRequestId, () => ( nextRequestId()));
7556
7984
  patchMeta(sliceId, { loadRequestId: requestId, saveState: "restoring" });
7557
7985
  const result = await persistence.load(workspaceId, descriptor, _nullishCoalesce(signal, () => ( new AbortController().signal)));
7558
- if (_optionalChain([signal, 'optionalAccess', _213 => _213.aborted]) || _optionalChain([get, 'call', _214 => _214(), 'access', _215 => _215.meta, 'access', _216 => _216[sliceId], 'optionalAccess', _217 => _217.loadRequestId]) !== requestId) {
7559
- if (_optionalChain([signal, 'optionalAccess', _218 => _218.aborted]) && _optionalChain([get, 'call', _219 => _219(), 'access', _220 => _220.meta, 'access', _221 => _221[sliceId], 'optionalAccess', _222 => _222.loadRequestId]) === requestId) {
7986
+ if (_optionalChain([signal, 'optionalAccess', _254 => _254.aborted]) || _optionalChain([get, 'call', _255 => _255(), 'access', _256 => _256.meta, 'access', _257 => _257[sliceId], 'optionalAccess', _258 => _258.loadRequestId]) !== requestId) {
7987
+ if (_optionalChain([signal, 'optionalAccess', _259 => _259.aborted]) && _optionalChain([get, 'call', _260 => _260(), 'access', _261 => _261.meta, 'access', _262 => _262[sliceId], 'optionalAccess', _263 => _263.loadRequestId]) === requestId) {
7560
7988
  patchMeta(sliceId, { saveState: "idle", loadRequestId: null });
7561
7989
  }
7562
7990
  return result;
@@ -7591,7 +8019,7 @@ function createFaStore({ contracts, descriptors, persistence, workspaceId }) {
7591
8019
  },
7592
8020
  async resetSlice(sliceId, signal, options) {
7593
8021
  const contract = requireContract(sliceId);
7594
- if (get().meta[sliceId].dirty && !_optionalChain([options, 'optionalAccess', _223 => _223.confirmed])) {
8022
+ if (get().meta[sliceId].dirty && !_optionalChain([options, 'optionalAccess', _264 => _264.confirmed])) {
7595
8023
  throw new Error(`Reset for slice ${sliceId} requires confirmation while unsaved changes exist`);
7596
8024
  }
7597
8025
  const defaultData = contract.createDefault();
@@ -7644,7 +8072,7 @@ function createInMemoryWorkspacePersistence(now = () => Date.now()) {
7644
8072
  }
7645
8073
  const saved = {
7646
8074
  ...clone(slice),
7647
- revision: (_nullishCoalesce(_optionalChain([current, 'optionalAccess', _224 => _224.revision]), () => ( 0))) + 1,
8075
+ revision: (_nullishCoalesce(_optionalChain([current, 'optionalAccess', _265 => _265.revision]), () => ( 0))) + 1,
7648
8076
  updatedAt: now(),
7649
8077
  ...resetAt !== void 0 ? { resetAt } : {}
7650
8078
  };
@@ -7725,7 +8153,7 @@ function createPersistenceCoordinator({
7725
8153
  if (disposed) return;
7726
8154
  const runtime = runtimeOf(sliceId);
7727
8155
  const meta = store.getState().meta[sliceId];
7728
- if (!_optionalChain([meta, 'optionalAccess', _225 => _225.dirty])) return;
8156
+ if (!_optionalChain([meta, 'optionalAccess', _266 => _266.dirty])) return;
7729
8157
  if (meta.saveState === "restoring" || meta.saveState === "saving") {
7730
8158
  runtime.pendingSave = true;
7731
8159
  return;
@@ -7753,7 +8181,7 @@ function createPersistenceCoordinator({
7753
8181
  return {
7754
8182
  async load(sliceId) {
7755
8183
  const runtime = runtimeOf(sliceId);
7756
- _optionalChain([runtime, 'access', _226 => _226.loadController, 'optionalAccess', _227 => _227.abort, 'call', _228 => _228()]);
8184
+ _optionalChain([runtime, 'access', _267 => _267.loadController, 'optionalAccess', _268 => _268.abort, 'call', _269 => _269()]);
7757
8185
  runtime.loadController = new AbortController();
7758
8186
  const controller = runtime.loadController;
7759
8187
  try {
@@ -7781,8 +8209,8 @@ function createPersistenceCoordinator({
7781
8209
  disposed = true;
7782
8210
  for (const runtime of runtimes.values()) {
7783
8211
  clearTimer(runtime);
7784
- _optionalChain([runtime, 'access', _229 => _229.loadController, 'optionalAccess', _230 => _230.abort, 'call', _231 => _231()]);
7785
- _optionalChain([runtime, 'access', _232 => _232.saveController, 'optionalAccess', _233 => _233.abort, 'call', _234 => _234()]);
8212
+ _optionalChain([runtime, 'access', _270 => _270.loadController, 'optionalAccess', _271 => _271.abort, 'call', _272 => _272()]);
8213
+ _optionalChain([runtime, 'access', _273 => _273.saveController, 'optionalAccess', _274 => _274.abort, 'call', _275 => _275()]);
7786
8214
  runtime.pendingSave = false;
7787
8215
  }
7788
8216
  runtimes.clear();
@@ -7886,7 +8314,7 @@ function parseLegacyLibraryFilters(source, knownTagIds) {
7886
8314
  return null;
7887
8315
  }).filter((id) => id !== null && knownTagIds.has(id));
7888
8316
  }
7889
- } catch (e36) {
8317
+ } catch (e37) {
7890
8318
  tagIds = [];
7891
8319
  }
7892
8320
  }
@@ -7897,7 +8325,7 @@ function parseLegacyLibraryFilters(source, knownTagIds) {
7897
8325
  if (Array.isArray(parsed)) {
7898
8326
  recentFilterTagIds = parsed.filter((entry) => typeof entry === "string" || typeof entry === "number").map((entry) => String(entry)).filter((id) => knownTagIds.has(id)).slice(0, 5);
7899
8327
  }
7900
- } catch (e37) {
8328
+ } catch (e38) {
7901
8329
  recentFilterTagIds = [];
7902
8330
  }
7903
8331
  }
@@ -7936,9 +8364,9 @@ function hatNavigationsziele(zugehoerigkeit) {
7936
8364
  var kennung = (wert) => typeof wert === "string" && wert.trim().length > 0;
7937
8365
  var kurz = (id) => id.slice(0, 8);
7938
8366
  function zugehoerigkeitOf(item) {
7939
- const runId = _optionalChain([item, 'optionalAccess', _235 => _235.szenen, 'optionalAccess', _236 => _236.prompt_run_id]);
8367
+ const runId = _optionalChain([item, 'optionalAccess', _276 => _276.szenen, 'optionalAccess', _277 => _277.prompt_run_id]);
7940
8368
  if (!kennung(runId)) return null;
7941
- const links = _nullishCoalesce(_optionalChain([item, 'optionalAccess', _237 => _237.szenen_links]), () => ( null));
8369
+ const links = _nullishCoalesce(_optionalChain([item, 'optionalAccess', _278 => _278.szenen_links]), () => ( null));
7942
8370
  if (!links || links.prompt_run_id !== runId) {
7943
8371
  return {
7944
8372
  run: null,
@@ -7969,15 +8397,15 @@ function zugehoerigkeitOf(item) {
7969
8397
  return { run, scene, hinweis: null };
7970
8398
  }
7971
8399
  function zugehoerigkeitenOf(item) {
7972
- const szenen = _optionalChain([item, 'optionalAccess', _238 => _238.szenen]);
8400
+ const szenen = _optionalChain([item, 'optionalAccess', _279 => _279.szenen]);
7973
8401
  if (!szenen) return [];
7974
8402
  const laeufe = [];
7975
8403
  const merken = (id) => {
7976
8404
  if (kennung(id) && !laeufe.includes(id)) laeufe.push(id);
7977
8405
  };
7978
8406
  merken(szenen.prompt_run_id);
7979
- for (const run of _nullishCoalesce(szenen.runs, () => ( []))) merken(_optionalChain([run, 'optionalAccess', _239 => _239.prompt_run_id]));
7980
- const linkFuer = (runId) => _nullishCoalesce((_nullishCoalesce(_optionalChain([item, 'optionalAccess', _240 => _240.szenen_run_links]), () => ( []))).find((l) => l.prompt_run_id === runId), () => ( (_optionalChain([item, 'optionalAccess', _241 => _241.szenen_links]) && item.szenen_links.prompt_run_id === runId ? item.szenen_links : null)));
8407
+ for (const run of _nullishCoalesce(szenen.runs, () => ( []))) merken(_optionalChain([run, 'optionalAccess', _280 => _280.prompt_run_id]));
8408
+ const linkFuer = (runId) => _nullishCoalesce((_nullishCoalesce(_optionalChain([item, 'optionalAccess', _281 => _281.szenen_run_links]), () => ( []))).find((l) => l.prompt_run_id === runId), () => ( (_optionalChain([item, 'optionalAccess', _282 => _282.szenen_links]) && item.szenen_links.prompt_run_id === runId ? item.szenen_links : null)));
7981
8409
  const ergebnis = [];
7982
8410
  for (const runId of laeufe) {
7983
8411
  const z = zugehoerigkeitOf({ szenen: { prompt_run_id: runId }, szenen_links: linkFuer(runId) });
@@ -8123,7 +8551,7 @@ function parseLegacyRecentTags(raw) {
8123
8551
  }
8124
8552
  return null;
8125
8553
  }).filter((entry) => entry !== null).slice(0, 10);
8126
- } catch (e38) {
8554
+ } catch (e39) {
8127
8555
  return [];
8128
8556
  }
8129
8557
  }
@@ -8252,4 +8680,8 @@ async function runTagsLegacyImport(options) {
8252
8680
 
8253
8681
 
8254
8682
 
8255
- exports.AvatarArchitectApp = AvatarArchitectApp; exports.CURRENT_TAG_EVENT_VERSION = CURRENT_TAG_EVENT_VERSION; exports.CollapsibleCard = CollapsibleCard; exports.CompactDropdown = CompactDropdown; exports.FaApp = FaApp; exports.FaToolsBadge = FaToolsBadge; exports.FlowBridgePanel = FlowBridgePanel; exports.FlowWorkspacePicker = FlowWorkspacePicker; exports.GLOBAL_STYLES = GLOBAL_STYLES; exports.HfMediaSyncTab = HfMediaSyncTab; exports.HistoryPanel = HistoryPanel; exports.InspectPanel = InspectPanel; exports.LIBRARY_CUTOVER_MARKER = LIBRARY_CUTOVER_MARKER; exports.LIBRARY_SLICE_SCHEMA_VERSION = LIBRARY_SLICE_SCHEMA_VERSION; exports.LIB_VERSION = version; exports.LabBlend = LabBlend; exports.LabCompare = LabCompare; exports.LabFrameExtractor = LabFrameExtractor; exports.LabImagePicker = LabImagePicker; exports.LabLoop = LabLoop; exports.LabRemix = LabRemix; exports.LabsTab = LabsTab; exports.LibraryView = LibraryView; exports.ListView = ListView; exports.MediaLibrary = MediaLibrary; exports.PillButton = PillButton; exports.PromptTab = PromptTab; exports.SCOPE_MAP = SCOPE_MAP; exports.SectionLabel = SectionLabel; exports.ServerTab = ServerTab; exports.SetupPanel = SetupPanel; exports.TAGS_CUTOVER_MARKER = TAGS_CUTOVER_MARKER; exports.TAGS_SLICE_SCHEMA_VERSION = TAGS_SLICE_SCHEMA_VERSION; exports.TagBaseSection = TagBaseSection; exports.TagManager = TagManager; exports.TagManagerPanel = TagManagerPanel; exports.ZugehoerigkeitLinks = ZugehoerigkeitLinks; exports.autoLabel = autoLabel; exports.buildBlendInstruction = buildBlendInstruction; exports.buildCompareInstruction = buildCompareInstruction; exports.buildFallbackPrompt = buildFallbackPrompt; exports.buildGenerationPrompt = buildGenerationPrompt; exports.buildImageGenerationOptions = buildImageGenerationOptions; exports.buildLoopInstruction = buildLoopInstruction; exports.buildPromptTabPayload = buildPromptTabPayload; exports.buildReferenceImageMediaIds = buildReferenceImageMediaIds; exports.buildRemixInstruction = buildRemixInstruction; exports.buildScanInstruction = buildScanInstruction; exports.cleanAiResponse = cleanAiResponse; exports.createFaStore = createFaStore; exports.createFlowBridgeClient = createFlowBridgeClient; exports.createFlowServices = createFlowServices; exports.createInMemoryLibraryDataSource = createInMemoryLibraryDataSource; exports.createInMemoryWorkspacePersistence = createInMemoryWorkspacePersistence; exports.createLibraryDefault = createLibraryDefault; exports.createPersistenceCoordinator = createPersistenceCoordinator; exports.createTagCreatedEvent = createTagCreatedEvent; exports.createTagUpdatedEvent = createTagUpdatedEvent; exports.createTagsDefault = createTagsDefault; exports.deriveTagBaseWorkspaceTags = deriveTagBaseWorkspaceTags; exports.deriveTagViewModel = deriveTagViewModel; exports.formatTreeToMarkdown = formatTreeToMarkdown; exports.frameToGeneration = frameToGeneration; exports.getFormattedTimestamp = getFormattedTimestamp; exports.getHFToken = _chunkVSHSZEGVjs.getHFToken; exports.getSessionClientId = _chunkVSHSZEGVjs.getSessionClientId; exports.groupGenerationsToLabItems = groupGenerationsToLabItems; exports.hatNavigationsziele = hatNavigationsziele; exports.hfBatchArchive = _chunkVSHSZEGVjs.hfBatchArchive; exports.hfBootstrapFromLegacy = _chunkVSHSZEGVjs.hfBootstrapFromLegacy; exports.hfListDir = _chunkVSHSZEGVjs.hfListDir; exports.hfLoadImageAsBase64 = _chunkVSHSZEGVjs.hfLoadImageAsBase64; exports.hfUploadImage = _chunkVSHSZEGVjs.hfUploadImage; exports.hfUploadSmallFile = _chunkVSHSZEGVjs.hfUploadSmallFile; exports.injectXMPMetadata = injectXMPMetadata; exports.interpretSdkError = interpretSdkError; exports.libraryContract = libraryContract; exports.libraryReactDescriptor = libraryReactDescriptor; exports.listCategories = listCategories; exports.loadHFState = _chunkVSHSZEGVjs.loadHFState; exports.loadPendingEvents = _chunkVSHSZEGVjs.loadPendingEvents; exports.loadTagBase = loadTagBase; exports.parseLegacyLibraryFilters = parseLegacyLibraryFilters; exports.parseLegacyRecentTags = parseLegacyRecentTags; exports.parsePromptFile = parsePromptFile; exports.parsePromptResponse = parsePromptResponse; exports.runLegacyMigration = runLegacyMigration; exports.runLibraryLegacyImport = runLibraryLegacyImport; exports.runTagsLegacyImport = runTagsLegacyImport; exports.setHFToken = _chunkVSHSZEGVjs.setHFToken; exports.tagsContract = tagsContract; exports.tagsReactDescriptor = tagsReactDescriptor; exports.tsFromEventPath = _chunkVSHSZEGVjs.tsFromEventPath; exports.useFaSlice = useFaSlice; exports.useFaSliceMeta = useFaSliceMeta; exports.useHFState = useHFState; exports.useKeyboardNavigation = useKeyboardNavigation; exports.useOnClickOutside = useOnClickOutside; exports.useTagBase = useTagBase; exports.validateTagBaseSelection = validateTagBaseSelection; exports.writeHFEvent = _chunkVSHSZEGVjs.writeHFEvent; exports.writeTagEvent = writeTagEvent; exports.zugehoerigkeitOf = zugehoerigkeitOf; exports.zugehoerigkeitenOf = zugehoerigkeitenOf;
8683
+
8684
+
8685
+
8686
+
8687
+ exports.AvatarArchitectApp = AvatarArchitectApp; exports.CURRENT_TAG_EVENT_VERSION = CURRENT_TAG_EVENT_VERSION; exports.CollapsibleCard = CollapsibleCard; exports.CompactDropdown = CompactDropdown; exports.FLOW_PROBE_MARKER = FLOW_PROBE_MARKER; exports.FLOW_PROBE_REQUEST = FLOW_PROBE_REQUEST; exports.FaApp = FaApp; exports.FaToolsBadge = FaToolsBadge; exports.FlowBridgePanel = FlowBridgePanel; exports.FlowWorkspacePicker = FlowWorkspacePicker; exports.GLOBAL_STYLES = GLOBAL_STYLES; exports.HfMediaSyncTab = HfMediaSyncTab; exports.HistoryPanel = HistoryPanel; exports.InspectPanel = InspectPanel; exports.LIBRARY_CUTOVER_MARKER = LIBRARY_CUTOVER_MARKER; exports.LIBRARY_SLICE_SCHEMA_VERSION = LIBRARY_SLICE_SCHEMA_VERSION; exports.LIB_VERSION = version; exports.LabBlend = LabBlend; exports.LabCompare = LabCompare; exports.LabFrameExtractor = LabFrameExtractor; exports.LabImagePicker = LabImagePicker; exports.LabLoop = LabLoop; exports.LabRemix = LabRemix; exports.LabsTab = LabsTab; exports.LibraryView = LibraryView; exports.ListView = ListView; exports.MediaLibrary = MediaLibrary; exports.PillButton = PillButton; exports.PromptTab = PromptTab; exports.SCOPE_MAP = SCOPE_MAP; exports.SectionLabel = SectionLabel; exports.ServerTab = ServerTab; exports.SetupPanel = SetupPanel; exports.TAGS_CUTOVER_MARKER = TAGS_CUTOVER_MARKER; exports.TAGS_SLICE_SCHEMA_VERSION = TAGS_SLICE_SCHEMA_VERSION; exports.TagBaseSection = TagBaseSection; exports.TagManager = TagManager; exports.TagManagerPanel = TagManagerPanel; exports.ZugehoerigkeitLinks = ZugehoerigkeitLinks; exports.autoLabel = autoLabel; exports.buildBlendInstruction = buildBlendInstruction; exports.buildCompareInstruction = buildCompareInstruction; exports.buildFallbackPrompt = buildFallbackPrompt; exports.buildGenerationPrompt = buildGenerationPrompt; exports.buildImageGenerationOptions = buildImageGenerationOptions; exports.buildLoopInstruction = buildLoopInstruction; exports.buildPromptTabPayload = buildPromptTabPayload; exports.buildReferenceImageMediaIds = buildReferenceImageMediaIds; exports.buildRemixInstruction = buildRemixInstruction; exports.buildScanInstruction = buildScanInstruction; exports.cleanAiResponse = cleanAiResponse; exports.createFaStore = createFaStore; exports.createFlowBridgeClient = createFlowBridgeClient; exports.createFlowServices = createFlowServices; exports.createInMemoryLibraryDataSource = createInMemoryLibraryDataSource; exports.createInMemoryWorkspacePersistence = createInMemoryWorkspacePersistence; exports.createLibraryDefault = createLibraryDefault; exports.createPersistenceCoordinator = createPersistenceCoordinator; exports.createTagCreatedEvent = createTagCreatedEvent; exports.createTagUpdatedEvent = createTagUpdatedEvent; exports.createTagsDefault = createTagsDefault; exports.deriveTagBaseWorkspaceTags = deriveTagBaseWorkspaceTags; exports.deriveTagViewModel = deriveTagViewModel; exports.executeFlowProbeBundle = executeFlowProbeBundle; exports.formatTreeToMarkdown = formatTreeToMarkdown; exports.frameToGeneration = frameToGeneration; exports.getFormattedTimestamp = getFormattedTimestamp; exports.getHFToken = _chunkVSHSZEGVjs.getHFToken; exports.getSessionClientId = _chunkVSHSZEGVjs.getSessionClientId; exports.groupGenerationsToLabItems = groupGenerationsToLabItems; exports.hatNavigationsziele = hatNavigationsziele; exports.hfBatchArchive = _chunkVSHSZEGVjs.hfBatchArchive; exports.hfBootstrapFromLegacy = _chunkVSHSZEGVjs.hfBootstrapFromLegacy; exports.hfListDir = _chunkVSHSZEGVjs.hfListDir; exports.hfLoadImageAsBase64 = _chunkVSHSZEGVjs.hfLoadImageAsBase64; exports.hfUploadImage = _chunkVSHSZEGVjs.hfUploadImage; exports.hfUploadSmallFile = _chunkVSHSZEGVjs.hfUploadSmallFile; exports.injectXMPMetadata = injectXMPMetadata; exports.interpretSdkError = interpretSdkError; exports.libraryContract = libraryContract; exports.libraryReactDescriptor = libraryReactDescriptor; exports.listCategories = listCategories; exports.loadHFState = _chunkVSHSZEGVjs.loadHFState; exports.loadPendingEvents = _chunkVSHSZEGVjs.loadPendingEvents; exports.loadTagBase = loadTagBase; exports.parseLegacyLibraryFilters = parseLegacyLibraryFilters; exports.parseLegacyRecentTags = parseLegacyRecentTags; exports.parsePromptFile = parsePromptFile; exports.parsePromptResponse = parsePromptResponse; exports.readFlowProbeBundle = readFlowProbeBundle; exports.runLegacyMigration = runLegacyMigration; exports.runLibraryLegacyImport = runLibraryLegacyImport; exports.runTagsLegacyImport = runTagsLegacyImport; exports.setHFToken = _chunkVSHSZEGVjs.setHFToken; exports.tagsContract = tagsContract; exports.tagsReactDescriptor = tagsReactDescriptor; exports.tsFromEventPath = _chunkVSHSZEGVjs.tsFromEventPath; exports.useFaSlice = useFaSlice; exports.useFaSliceMeta = useFaSliceMeta; exports.useHFState = useHFState; exports.useKeyboardNavigation = useKeyboardNavigation; exports.useOnClickOutside = useOnClickOutside; exports.useTagBase = useTagBase; exports.validateTagBaseSelection = validateTagBaseSelection; exports.writeHFEvent = _chunkVSHSZEGVjs.writeHFEvent; exports.writeTagEvent = writeTagEvent; exports.zugehoerigkeitOf = zugehoerigkeitOf; exports.zugehoerigkeitenOf = zugehoerigkeitenOf;