@rslsp1/fa-app-tools 10.3.5 → 10.3.6

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.d.mts CHANGED
@@ -6,7 +6,7 @@ import { Node, Edge } from '@xyflow/react';
6
6
  import * as zustand_vanilla from 'zustand/vanilla';
7
7
  import { F as FeatureSliceId, b as SliceContract, a as PersistenceDescriptor, W as WorkspacePersistence, P as PersistedSlice, L as LoadResult, g as WriteResult, f as WorkspaceTabId, C as CommandResult, R as RequestContext, Q as QueryResult } from './contracts-B3AbzYQ4.mjs';
8
8
 
9
- var version = "10.3.5";
9
+ var version = "10.3.6";
10
10
 
11
11
  declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
12
12
 
@@ -359,21 +359,16 @@ interface FlowBridgeResponse {
359
359
  roundTripMs: number;
360
360
  error: FlowBridgeError | null;
361
361
  }
362
- type FlowBridgeConnection = {
363
- ok: true;
362
+ /** App-Proxy (#639): ein GET der Fine-Art-App ueber den MCP-Host des Ziels, Zugang ueber die Token-Endung. */
363
+ interface FlowBridgeProxyRequest {
364
364
  env: 'dev' | 'prod';
365
- server: string;
366
- waitedMs: number;
367
- } | {
368
- ok: false;
369
- error: FlowBridgeError;
370
- waitedMs: number;
371
- };
365
+ tokenSuffix: string;
366
+ method: 'GET';
367
+ path: string;
368
+ }
372
369
  interface FlowBridgeClient {
373
- /** App-Proxy (#639): bittet um Freigabe fuer dieses Dokument; erfuellt erst nach Entscheidung im Popup. */
374
- connect?(env: 'dev' | 'prod', options?: {
375
- timeoutMs?: number;
376
- }): Promise<FlowBridgeConnection>;
370
+ /** App-Proxy (#639): ein lesender Request ueber den Daten-Proxy (z. B. Pruefung des Datenzugangs). */
371
+ proxy?(request: FlowBridgeProxyRequest): Promise<FlowBridgeResponse>;
377
372
  status(): Promise<FlowBridgeStatus>;
378
373
  /** `timeoutMs` ersetzt das Warten der Seite fuer diesen Request (App-Bundle: laenger als das Extension-Timeout). */
379
374
  request(request: FlowBridgeRequest, options?: {
package/dist/index.d.ts CHANGED
@@ -6,7 +6,7 @@ import { Node, Edge } from '@xyflow/react';
6
6
  import * as zustand_vanilla from 'zustand/vanilla';
7
7
  import { F as FeatureSliceId, b as SliceContract, a as PersistenceDescriptor, W as WorkspacePersistence, P as PersistedSlice, L as LoadResult, g as WriteResult, f as WorkspaceTabId, C as CommandResult, R as RequestContext, Q as QueryResult } from './contracts-B3AbzYQ4.js';
8
8
 
9
- var version = "10.3.5";
9
+ var version = "10.3.6";
10
10
 
11
11
  declare function useOnClickOutside(ref: RefObject<HTMLElement | null>, handler: (e: MouseEvent | TouchEvent) => void): void;
12
12
 
@@ -359,21 +359,16 @@ interface FlowBridgeResponse {
359
359
  roundTripMs: number;
360
360
  error: FlowBridgeError | null;
361
361
  }
362
- type FlowBridgeConnection = {
363
- ok: true;
362
+ /** App-Proxy (#639): ein GET der Fine-Art-App ueber den MCP-Host des Ziels, Zugang ueber die Token-Endung. */
363
+ interface FlowBridgeProxyRequest {
364
364
  env: 'dev' | 'prod';
365
- server: string;
366
- waitedMs: number;
367
- } | {
368
- ok: false;
369
- error: FlowBridgeError;
370
- waitedMs: number;
371
- };
365
+ tokenSuffix: string;
366
+ method: 'GET';
367
+ path: string;
368
+ }
372
369
  interface FlowBridgeClient {
373
- /** App-Proxy (#639): bittet um Freigabe fuer dieses Dokument; erfuellt erst nach Entscheidung im Popup. */
374
- connect?(env: 'dev' | 'prod', options?: {
375
- timeoutMs?: number;
376
- }): Promise<FlowBridgeConnection>;
370
+ /** App-Proxy (#639): ein lesender Request ueber den Daten-Proxy (z. B. Pruefung des Datenzugangs). */
371
+ proxy?(request: FlowBridgeProxyRequest): Promise<FlowBridgeResponse>;
377
372
  status(): Promise<FlowBridgeStatus>;
378
373
  /** `timeoutMs` ersetzt das Warten der Seite fuer diesen Request (App-Bundle: laenger als das Extension-Timeout). */
379
374
  request(request: FlowBridgeRequest, options?: {
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.5";
25
+ var version = "10.3.6";
26
26
 
27
27
  // src/hooks/useOnClickOutside.ts
28
28
  var _react = require('react'); var _react2 = _interopRequireDefault(_react);
@@ -5538,7 +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
+ var FLOW_BRIDGE_PROXY_TIMEOUT_MS = 75e3;
5542
5542
  function isRecord(value) {
5543
5543
  return value !== null && typeof value === "object" && !Array.isArray(value);
5544
5544
  }
@@ -5605,15 +5605,24 @@ function createFlowBridgeClient({
5605
5605
  }
5606
5606
  return { available: true, name: bridge.name, version: bridge.version, protocol: bridge.protocol, roundTripMs };
5607
5607
  },
5608
- async connect(env, { timeoutMs = FLOW_BRIDGE_CONNECT_TIMEOUT_MS } = {}) {
5608
+ async proxy({ env, tokenSuffix, method, path }) {
5609
5609
  const started = clock();
5610
- const reply = await exchange({ op: "connect", env }, timeoutMs);
5611
- const waitedMs = Math.round(clock() - started);
5610
+ const reply = await exchange({ op: "proxy", env, tokenSuffix, method, path }, FLOW_BRIDGE_PROXY_TIMEOUT_MS);
5611
+ const roundTripMs = Math.round(clock() - started);
5612
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 };
5613
+ return { ok: false, transport: null, status: null, data: null, latencyMs: null, roundTripMs, error: noBridge(FLOW_BRIDGE_PROXY_TIMEOUT_MS) };
5614
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 };
5615
+ const ok = reply.ok === true;
5616
+ const body = isRecord(reply.body) && reply.body.encoding === "text" && typeof reply.body.data === "string" ? reply.body.data : null;
5617
+ return {
5618
+ ok,
5619
+ transport: typeof reply.transport === "string" ? reply.transport : null,
5620
+ status: nullableNumber(reply.status),
5621
+ data: ok ? body : null,
5622
+ latencyMs: nullableNumber(reply.latencyMs),
5623
+ roundTripMs,
5624
+ error: ok ? null : readError(reply.error)
5625
+ };
5617
5626
  },
5618
5627
  async request(request, { timeoutMs = requestTimeoutMs } = {}) {
5619
5628
  const started = clock();
@@ -6025,7 +6034,7 @@ function stepText(step) {
6025
6034
  }
6026
6035
  var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) => {
6027
6036
  const bridge = _react.useMemo.call(void 0, () => _nullishCoalesce(client, () => ( createFlowBridgeClient({ appVersion }))), [client, appVersion]);
6028
- const [connection, setConnection] = _react.useState.call(void 0, null);
6037
+ const [access, setAccess] = _react.useState.call(void 0, null);
6029
6038
  const [steps, setSteps] = _react.useState.call(void 0, []);
6030
6039
  const [load, setLoad] = _react.useState.call(void 0, null);
6031
6040
  const [renderError, setRenderError] = _react.useState.call(void 0, null);
@@ -6036,10 +6045,10 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6036
6045
  if (!tokenSuffix) return void 0;
6037
6046
  let active = true;
6038
6047
  void (async () => {
6039
- const connected = bridge.connect ? await bridge.connect(environment) : { ok: false, error: { code: "no-bridge", message: "Bridge-Client ohne connect." }, waitedMs: 0 };
6048
+ const checked = bridge.proxy ? await bridge.proxy({ env: environment, tokenSuffix, method: "GET", path: "/api/status" }) : { ok: false, transport: null, status: null, data: null, latencyMs: null, roundTripMs: 0, error: { code: "no-bridge", message: "Bridge-Client ohne proxy." } };
6040
6049
  if (!active) return;
6041
- setConnection(connected);
6042
- if (!connected.ok) return;
6050
+ setAccess(checked);
6051
+ if (!checked.ok || checked.status !== 200) return;
6043
6052
  const result = await loadFlowApp({ bridge, environment, tokenSuffix, onStep: (next) => {
6044
6053
  if (active) setSteps(next);
6045
6054
  } });
@@ -6063,7 +6072,9 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6063
6072
  customTabs: [],
6064
6073
  apiKey: null,
6065
6074
  backendUrl: load.backendUrl,
6066
- transport: "flow-bridge"
6075
+ transport: "flow-bridge",
6076
+ bridgeEnv: environment,
6077
+ bridgeTokenSuffix: tokenSuffix
6067
6078
  }));
6068
6079
  } catch (error) {
6069
6080
  setRenderError(error instanceof Error ? error.message : String(error));
@@ -6072,8 +6083,9 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6072
6083
  _optionalChain([root, 'optionalAccess', _195 => _195.unmount, 'call', _196 => _196()]);
6073
6084
  style.remove();
6074
6085
  };
6075
- }, [load]);
6076
- const failed = !tokenSuffix || connection !== null && !connection.ok || load !== null && !load.ok || renderError !== null;
6086
+ }, [load, environment, tokenSuffix]);
6087
+ const accessFailed = access !== null && (!access.ok || access.status !== 200);
6088
+ const failed = !tokenSuffix || accessFailed || load !== null && !load.ok || renderError !== null;
6077
6089
  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
6090
  /* @__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
6091
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "button", { type: "button", onClick: onClose, className: "font-bold text-white/80", children: "\u2190 FlowFA" }),
@@ -6081,14 +6093,15 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6081
6093
  ] }),
6082
6094
  !_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
6095
  !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." }),
6096
+ tokenSuffix && !access && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "data-testid": "flow-fine-art-app-access", className: "text-white/60", children: `Datenzugang ${environment.toUpperCase()} wird gepr\xFCft \u2026` }),
6097
+ access && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { "data-testid": "flow-fine-art-app-access", style: { color: accessFailed ? "#f87171" : "rgba(255,255,255,0.6)" }, children: access.ok ? `Datenzugang: GET /api/status \u2192 HTTP ${access.status} \xB7 ${_nullishCoalesce(access.transport, () => ( "kein Transport"))} \xB7 ${access.roundTripMs} ms` : `Datenzugang: ${_optionalChain([access, 'access', _198 => _198.error, 'optionalAccess', _199 => _199.code])}: ${_optionalChain([access, 'access', _200 => _200.error, 'optionalAccess', _201 => _201.message])}` }),
6098
+ _optionalChain([access, 'optionalAccess', _202 => _202.error, 'optionalAccess', _203 => _203.code]) === "not-approved" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { color: "#fbbf24" }, children: `Extension-Popup \u201EFine-Art Flow Bridge\u201C \u2192 Fine-Art App: Datenzugang \u2192 ${environment.toUpperCase()} einschalten, dann neu starten.` }),
6099
+ accessFailed && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { role: "alert", className: "font-bold", style: { color: "#f87171" }, children: "App nicht gestartet \u2014 ohne Datenzugang erreicht sie ihren Server nicht." }),
6087
6100
  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
6101
  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
6102
  ] }),
6090
6103
  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" } })
6104
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: appRootRef, className: "flex-1 overflow-auto", style: { display: _optionalChain([load, 'optionalAccess', _204 => _204.ok]) && !failed ? "block" : "none" } })
6092
6105
  ] });
6093
6106
  };
6094
6107
 
@@ -6297,7 +6310,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6297
6310
  const loadThumbnailsForEntries = _react.useCallback.call(void 0, async (entries) => {
6298
6311
  await loadThumbnailsSequentially(entries, {
6299
6312
  inFlight: hfInFlightRef.current,
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]),
6313
+ isAlreadyLoaded: (entry) => !!_optionalChain([galleryItemsRef, 'access', _205 => _205.current, 'access', _206 => _206.find, 'call', _207 => _207((g) => g.id === entry.id), 'optionalAccess', _208 => _208.base64]),
6301
6314
  isKnownMissing: (entry) => hfImageNotFoundRef.current.has(entry.id),
6302
6315
  loadImage: (entry) => _chunkVSHSZEGVjs.hfLoadImageAsBase64.call(void 0, entry.id, hfToken, effectiveNamespace, entry.filename, void 0, entry.mimeType, entry.hasThumb),
6303
6316
  onLoaded: (entry, b64) => {
@@ -6316,7 +6329,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6316
6329
  }, [hfToken, effectiveNamespace]);
6317
6330
  _react.useEffect.call(void 0, () => {
6318
6331
  if (!hfState) return;
6319
- if (_optionalChain([hfState, 'access', _203 => _203.tags, 'optionalAccess', _204 => _204.by_category])) setWorkspaceTags(hfState.tags);
6332
+ if (_optionalChain([hfState, 'access', _209 => _209.tags, 'optionalAccess', _210 => _210.by_category])) setWorkspaceTags(hfState.tags);
6320
6333
  const hfIds = new Set(hfState.metadata.map((m) => m.id));
6321
6334
  const skeletons = hfState.metadata.map((m) => ({
6322
6335
  id: m.id,
@@ -6414,14 +6427,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6414
6427
  const [zoomOffset, setZoomOffset] = _react.useState.call(void 0, { x: 0, y: 0 });
6415
6428
  const { historyVisible, galleryVisible } = computePrefetchVisibility({
6416
6429
  layoutChoice,
6417
- appShellVisible: !showStart && !requireWorkspaceSelection && !(isFullscreen && !!_optionalChain([currentResult, 'optionalAccess', _205 => _205.base64])),
6430
+ appShellVisible: !showStart && !requireWorkspaceSelection && !(isFullscreen && !!_optionalChain([currentResult, 'optionalAccess', _211 => _211.base64])),
6418
6431
  mobileTab,
6419
6432
  middlePanel,
6420
6433
  activeTab,
6421
6434
  isRightCollapsed
6422
6435
  });
6423
6436
  useThumbnailPrefetch({
6424
- metadata: _optionalChain([hfState, 'optionalAccess', _206 => _206.metadata]),
6437
+ metadata: _optionalChain([hfState, 'optionalAccess', _212 => _212.metadata]),
6425
6438
  historyVisible,
6426
6439
  galleryVisible,
6427
6440
  historyVisibleCount,
@@ -6482,7 +6495,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6482
6495
  };
6483
6496
  const handleSelectReference = async () => {
6484
6497
  const media = await onSelectMedia();
6485
- if (!_optionalChain([media, 'optionalAccess', _207 => _207.length])) return;
6498
+ if (!_optionalChain([media, 'optionalAccess', _213 => _213.length])) return;
6486
6499
  const first = media[0];
6487
6500
  if (first.mediaId) {
6488
6501
  setActiveReferenceId(first.mediaId);
@@ -6505,7 +6518,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6505
6518
  generateImage: onGenerateImage,
6506
6519
  saveResult: async (item) => {
6507
6520
  const frame = item.frames[0];
6508
- if (_optionalChain([frame, 'optionalAccess', _208 => _208.base64])) {
6521
+ if (_optionalChain([frame, 'optionalAccess', _214 => _214.base64])) {
6509
6522
  const gen = frameToGeneration(frame, item);
6510
6523
  setGalleryItems((prev) => [gen, ...prev]);
6511
6524
  setHistory((prev) => [gen, ...prev]);
@@ -6573,7 +6586,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6573
6586
  setIsScanningImage(false);
6574
6587
  }
6575
6588
  };
6576
- const currentIndex = _react.useMemo.call(void 0, () => history.findIndex((h) => h.id === _optionalChain([currentResult, 'optionalAccess', _209 => _209.id])), [history, currentResult]);
6589
+ const currentIndex = _react.useMemo.call(void 0, () => history.findIndex((h) => h.id === _optionalChain([currentResult, 'optionalAccess', _215 => _215.id])), [history, currentResult]);
6577
6590
  const goToPrev = _react.useCallback.call(void 0, () => {
6578
6591
  if (currentIndex > 0) setCurrentResult(history[currentIndex - 1]);
6579
6592
  }, [currentIndex, history]);
@@ -6587,7 +6600,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6587
6600
  _chunkVSHSZEGVjs.hfLoadImageAsBase64.call(void 0, g.id, hfToken, effectiveNamespace, g.filename, void 0, g.mimeType, false).then((b64) => {
6588
6601
  if (!b64) return;
6589
6602
  const full = `data:${g.mimeType || "image/jpeg"};base64,${b64}`;
6590
- setCurrentResult((prev) => _optionalChain([prev, 'optionalAccess', _210 => _210.id]) === g.id ? { ...prev, fullBase64: full } : prev);
6603
+ setCurrentResult((prev) => _optionalChain([prev, 'optionalAccess', _216 => _216.id]) === g.id ? { ...prev, fullBase64: full } : prev);
6591
6604
  setGalleryItems((prev) => prev.map((item) => item.id === g.id ? { ...item, fullBase64: full } : item));
6592
6605
  }).catch(() => {
6593
6606
  });
@@ -6603,13 +6616,13 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6603
6616
  }
6604
6617
  }, [hfToken, effectiveNamespace, hfWriteEvent]);
6605
6618
  const currentGroup = _react.useMemo.call(void 0, () => {
6606
- if (!_optionalChain([currentResult, 'optionalAccess', _211 => _211.prompt])) return [];
6619
+ if (!_optionalChain([currentResult, 'optionalAccess', _217 => _217.prompt])) return [];
6607
6620
  const groups = groupByPrompt(galleryItems.filter((g) => g.status === "done" && !!g.base64));
6608
6621
  const group = groups.find((gr) => gr.prompt === currentResult.prompt);
6609
6622
  return group ? group.items : [];
6610
- }, [galleryItems, _optionalChain([currentResult, 'optionalAccess', _212 => _212.prompt])]);
6623
+ }, [galleryItems, _optionalChain([currentResult, 'optionalAccess', _218 => _218.prompt])]);
6611
6624
  _react.useEffect.call(void 0, () => {
6612
- if (!_optionalChain([currentResult, 'optionalAccess', _213 => _213.prompt]) || !hfToken || !effectiveNamespace || !hfState) return;
6625
+ if (!_optionalChain([currentResult, 'optionalAccess', _219 => _219.prompt]) || !hfToken || !effectiveNamespace || !hfState) return;
6613
6626
  const siblings = galleryItemsRef.current.filter(
6614
6627
  (g) => g.prompt === currentResult.prompt && !g.base64 && !hfImageNotFoundRef.current.has(g.id)
6615
6628
  );
@@ -6632,7 +6645,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6632
6645
  }
6633
6646
  }
6634
6647
  })();
6635
- }, [_optionalChain([currentResult, 'optionalAccess', _214 => _214.id]), _optionalChain([currentResult, 'optionalAccess', _215 => _215.prompt])]);
6648
+ }, [_optionalChain([currentResult, 'optionalAccess', _220 => _220.id]), _optionalChain([currentResult, 'optionalAccess', _221 => _221.prompt])]);
6636
6649
  const hcStyle = highContrast ? { filter: "brightness(1.6) contrast(1.05)" } : void 0;
6637
6650
  const runningBadge = activeGenerationsCount > 0 ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6638
6651
  "div",
@@ -6713,7 +6726,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6713
6726
  const errorGen = { ...newGen, status: "error", error: { message: err.message || "Unbekannter Fehler", details: err.toString() } };
6714
6727
  setHistory((prev) => prev.map((g) => g.id === genId ? errorGen : g));
6715
6728
  setGalleryItems((prev) => prev.filter((g) => g.id !== genId));
6716
- if (!options.silent || _optionalChain([currentResult, 'optionalAccess', _216 => _216.id]) === genId) setCurrentResult(errorGen);
6729
+ if (!options.silent || _optionalChain([currentResult, 'optionalAccess', _222 => _222.id]) === genId) setCurrentResult(errorGen);
6717
6730
  } finally {
6718
6731
  setActiveGenerationsCount((prev) => Math.max(0, prev - 1));
6719
6732
  }
@@ -6849,7 +6862,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6849
6862
  }
6850
6863
  };
6851
6864
  const handleDownloadSingle = async () => {
6852
- if (!_optionalChain([currentResult, 'optionalAccess', _217 => _217.base64])) return;
6865
+ if (!_optionalChain([currentResult, 'optionalAccess', _223 => _223.base64])) return;
6853
6866
  try {
6854
6867
  const downloadSrc = currentResult.fullBase64 || currentResult.base64;
6855
6868
  const base64Data = downloadSrc.split(",")[1];
@@ -6865,9 +6878,9 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6865
6878
  const reader = new FileReader();
6866
6879
  reader.onload = (ev) => {
6867
6880
  try {
6868
- const root = JSON.parse(_optionalChain([ev, 'access', _218 => _218.target, 'optionalAccess', _219 => _219.result]));
6881
+ const root = JSON.parse(_optionalChain([ev, 'access', _224 => _224.target, 'optionalAccess', _225 => _225.result]));
6869
6882
  const rawTags = root.tags || root;
6870
- if (!_optionalChain([rawTags, 'optionalAccess', _220 => _220.by_category])) return;
6883
+ if (!_optionalChain([rawTags, 'optionalAccess', _226 => _226.by_category])) return;
6871
6884
  const filtered = {};
6872
6885
  const EXCLUDED2 = ["pdf-export", "book.micro-edit-rules"];
6873
6886
  Object.entries(rawTags.by_category).forEach(([cat, items]) => {
@@ -6884,7 +6897,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6884
6897
  };
6885
6898
  const handleHfInitialSync = async (onProgress) => {
6886
6899
  if (!hfToken || !effectiveNamespace) return;
6887
- const existingIds = new Set((_optionalChain([hfState, 'optionalAccess', _221 => _221.metadata]) || []).map((m) => m.id));
6900
+ const existingIds = new Set((_optionalChain([hfState, 'optionalAccess', _227 => _227.metadata]) || []).map((m) => m.id));
6888
6901
  const gens = galleryItems.filter((g) => g.base64 && g.status === "done" && !existingIds.has(g.id));
6889
6902
  const total = gens.length;
6890
6903
  onProgress(0, total);
@@ -6910,7 +6923,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6910
6923
  }
6911
6924
  };
6912
6925
  const mergeWorkspaceTags = (local, remote) => {
6913
- if (!_optionalChain([remote, 'optionalAccess', _222 => _222.by_category])) return local;
6926
+ if (!_optionalChain([remote, 'optionalAccess', _228 => _228.by_category])) return local;
6914
6927
  const merged = {};
6915
6928
  const allCategories = /* @__PURE__ */ new Set([...Object.keys(local.by_category), ...Object.keys(remote.by_category)]);
6916
6929
  for (const cat of allCategories) {
@@ -6920,7 +6933,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6920
6933
  const localValues = new Set(localTags.map((t) => t.value));
6921
6934
  const mergedLocal = localTags.map((t) => {
6922
6935
  const remote2 = remoteMap.get(t.value);
6923
- return _optionalChain([remote2, 'optionalAccess', _223 => _223.is_deleted]) ? { ...t, is_deleted: true } : t;
6936
+ return _optionalChain([remote2, 'optionalAccess', _229 => _229.is_deleted]) ? { ...t, is_deleted: true } : t;
6924
6937
  });
6925
6938
  const onlyInRemote = remoteTags.filter((t) => !localValues.has(t.value));
6926
6939
  merged[cat] = [...mergedLocal, ...onlyInRemote];
@@ -6928,7 +6941,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
6928
6941
  const all = Object.entries(merged).flatMap(([cat, tags]) => tags.map((t) => ({ ...t, category: cat })));
6929
6942
  return { by_category: merged, all };
6930
6943
  };
6931
- if (isFullscreen && _optionalChain([currentResult, 'optionalAccess', _224 => _224.base64])) {
6944
+ if (isFullscreen && _optionalChain([currentResult, 'optionalAccess', _230 => _230.base64])) {
6932
6945
  const fsRaw = currentResult.fullBase64 || currentResult.base64;
6933
6946
  const fsBase64 = fsRaw.startsWith("data:") ? fsRaw : `data:image/png;base64,${fsRaw}`;
6934
6947
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -7160,7 +7173,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7160
7173
  }, children: [
7161
7174
  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) => {
7162
7175
  const frame = item.frames[0];
7163
- if (_optionalChain([frame, 'optionalAccess', _225 => _225.base64])) {
7176
+ if (_optionalChain([frame, 'optionalAccess', _231 => _231.base64])) {
7164
7177
  setCurrentResult(frameToGeneration(frame, item));
7165
7178
  setMobileTab("stage");
7166
7179
  }
@@ -7184,7 +7197,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7184
7197
  /* @__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" }] }),
7185
7198
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
7186
7199
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex-1" }),
7187
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _226 => _226.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7200
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _232 => _232.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7188
7201
  runningBadge,
7189
7202
  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: [
7190
7203
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: activeReferenceThumbnail, className: "h-full aspect-square object-cover" }),
@@ -7235,21 +7248,21 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7235
7248
  setTouchStartX(null);
7236
7249
  },
7237
7250
  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: [
7251
+ _optionalChain([currentResult, 'optionalAccess', _233 => _233.status]) === "processing" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-3 opacity-40", children: [
7239
7252
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
7240
7253
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[11px] uppercase font-bold tracking-widest", children: "Erstelle Bild..." })
7241
7254
  ] }),
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: [
7255
+ _optionalChain([currentResult, 'optionalAccess', _234 => _234.status]) === "error" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "p-6 text-center flex flex-col items-center gap-3", children: [
7243
7256
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-red-400 text-[36px]", children: "warning" }),
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]) }),
7257
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-white/50 text-[13px]", children: _optionalChain([currentResult, 'access', _235 => _235.error, 'optionalAccess', _236 => _236.message]) }),
7245
7258
  /* @__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" })
7246
7259
  ] }),
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" }),
7260
+ _optionalChain([currentResult, 'optionalAccess', _237 => _237.status]) === "done" && currentResult.base64 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: currentResult.fullBase64 || currentResult.base64, className: "w-full h-full object-contain" }),
7248
7261
  !currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col items-center gap-2 opacity-10", children: [
7249
7262
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[64px]", children: "palette" }),
7250
7263
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[11px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
7251
7264
  ] }),
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" }) }),
7265
+ _optionalChain([currentResult, 'optionalAccess', _238 => _238.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" }) }),
7253
7266
  history.length > 1 && currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
7254
7267
  /* @__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" }) }),
7255
7268
  /* @__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" }) }),
@@ -7262,7 +7275,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7262
7275
  ]
7263
7276
  }
7264
7277
  ),
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: [
7278
+ _optionalChain([currentResult, 'optionalAccess', _239 => _239.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: [
7266
7279
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7267
7280
  "div",
7268
7281
  {
@@ -7305,7 +7318,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7305
7318
  }
7306
7319
  )
7307
7320
  ] }, item.id)) }),
7308
- _optionalChain([currentResult, 'optionalAccess', _234 => _234.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2 mt-3", children: [
7321
+ _optionalChain([currentResult, 'optionalAccess', _240 => _240.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-2 mt-3", children: [
7309
7322
  /* @__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: [
7310
7323
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[18px] text-white/60", children: "replay" }),
7311
7324
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[12px] text-white/60", children: "Prompt" })
@@ -7327,14 +7340,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7327
7340
  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" }) })
7328
7341
  ] }),
7329
7342
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 overflow-hidden relative", children: [
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) }),
7343
+ activeTab === "history" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _241 => _241.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
7331
7344
  activeTab === "gallery" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7332
7345
  MediaLibrary,
7333
7346
  {
7334
7347
  items: galleryItems,
7335
7348
  onImport: async () => {
7336
7349
  const media = await onSelectMedia();
7337
- if (!_optionalChain([media, 'optionalAccess', _236 => _236.length])) return;
7350
+ if (!_optionalChain([media, 'optionalAccess', _242 => _242.length])) return;
7338
7351
  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]);
7339
7352
  },
7340
7353
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
@@ -7482,7 +7495,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7482
7495
  /* @__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" }] }),
7483
7496
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CompactDropdown, { value: String(imageCount), displayValue: `${imageCount}\xD7`, onChange: updateImageCount, options: imageCountOptions }),
7484
7497
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { style: { flex: 1 } }),
7485
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _237 => _237.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7498
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _243 => _243.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7486
7499
  runningBadge,
7487
7500
  /* @__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" }) }),
7488
7501
  /* @__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" }) })
@@ -7511,7 +7524,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7511
7524
  ]
7512
7525
  }
7513
7526
  ) }),
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) }) })
7527
+ /* @__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', _244 => _244.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }) })
7515
7528
  ] }),
7516
7529
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { flex: 1, height: tlH, display: "flex", flexDirection: "column", background: "#0b0b0b" }, children: [
7517
7530
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -7527,21 +7540,21 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7527
7540
  setTouchStartX(null);
7528
7541
  },
7529
7542
  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: [
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: [
7543
+ _optionalChain([currentResult, 'optionalAccess', _245 => _245.status]) === "processing" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 12, opacity: 0.4 }, children: [
7531
7544
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 36 }, children: "hourglass_top" }),
7532
7545
  /* @__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..." })
7533
7546
  ] }),
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: [
7547
+ _optionalChain([currentResult, 'optionalAccess', _246 => _246.status]) === "error" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { padding: 24, textAlign: "center", display: "flex", flexDirection: "column", alignItems: "center", gap: 12 }, children: [
7535
7548
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 32, color: "#f87171" }, children: "warning" }),
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]) }),
7549
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { style: { fontSize: 11, color: "rgba(255,255,255,0.5)", margin: 0 }, children: _optionalChain([currentResult, 'access', _247 => _247.error, 'optionalAccess', _248 => _248.message]) }),
7537
7550
  /* @__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" })
7538
7551
  ] }),
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" } }),
7552
+ _optionalChain([currentResult, 'optionalAccess', _249 => _249.status]) === "done" && currentResult.base64 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "img", { src: currentResult.fullBase64 || currentResult.base64, style: { maxWidth: "100%", maxHeight: "100%", objectFit: "contain" } }),
7540
7553
  !currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { display: "flex", flexDirection: "column", alignItems: "center", gap: 8, opacity: 0.1 }, children: [
7541
7554
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 64 }, children: "palette" }),
7542
7555
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { style: { fontSize: 11, fontWeight: "bold", textTransform: "uppercase", letterSpacing: "0.2em" }, children: "Avatar Architect" })
7543
7556
  ] }),
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" }) }),
7557
+ _optionalChain([currentResult, 'optionalAccess', _250 => _250.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" }) }),
7545
7558
  history.length > 1 && currentResult && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
7546
7559
  /* @__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" }) }),
7547
7560
  /* @__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" }) }),
@@ -7554,7 +7567,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7554
7567
  ] })
7555
7568
  }
7556
7569
  ),
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: [
7570
+ _optionalChain([currentResult, 'optionalAccess', _251 => _251.status]) === "done" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { style: { padding: "0 16px 16px", display: "flex", gap: 8, flexShrink: 0 }, children: [
7558
7571
  /* @__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: [
7559
7572
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "replay" }),
7560
7573
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Prompt" })
@@ -7676,7 +7689,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7676
7689
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Ref" })
7677
7690
  ] }),
7678
7691
  /* @__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" }) }),
7679
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _246 => _246.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7692
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TaskExecutor, { openTasks: _optionalChain([hfState, 'optionalAccess', _252 => _252.openTasks]) || {}, onExecute: handleExecuteTask, onTaskCompleted: handleTaskCompleted }),
7680
7693
  runningBadge,
7681
7694
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PillButton, { variant: "solid", icon: "bolt", disabled: !activePrompt.trim(), onClick: () => handleGenerateBatch(), children: "Generieren" })
7682
7695
  ] })
@@ -7688,7 +7701,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7688
7701
  ] }) }),
7689
7702
  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) => {
7690
7703
  const frame = item.frames[0];
7691
- if (_optionalChain([frame, 'optionalAccess', _247 => _247.base64])) setCurrentResult(frameToGeneration(frame, item));
7704
+ if (_optionalChain([frame, 'optionalAccess', _253 => _253.base64])) setCurrentResult(frameToGeneration(frame, item));
7692
7705
  } }) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1 overflow-hidden flex flex-col", children: [
7693
7706
  /* @__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: [
7694
7707
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[40px]", children: "hourglass_top" }),
@@ -7697,7 +7710,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7697
7710
  /* @__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" }) }),
7698
7711
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2", children: [
7699
7712
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-[11px] font-bold uppercase tracking-widest text-red-400", children: "Generierungsfehler" }),
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]) })
7713
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-white/60 text-[12px] leading-relaxed", children: _optionalChain([currentResult, 'access', _254 => _254.error, 'optionalAccess', _255 => _255.message]) })
7701
7714
  ] }),
7702
7715
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PillButton, { variant: "outline", icon: "refresh", onClick: () => handleGenerateImage(currentResult.prompt), children: "Erneut versuchen" })
7703
7716
  ] }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "h-full w-full relative flex items-center justify-center", children: [
@@ -7711,7 +7724,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7711
7724
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[100px]", children: "palette" }),
7712
7725
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-[12px] font-bold uppercase tracking-[0.2em]", children: "Avatar Architect" })
7713
7726
  ] }) }) }),
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: [
7727
+ _optionalChain([currentResult, 'optionalAccess', _256 => _256.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: [
7715
7728
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7716
7729
  "div",
7717
7730
  {
@@ -7792,14 +7805,14 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
7792
7805
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "material-symbols-outlined text-[40px] text-white/10 block mb-3", children: "label_off" }),
7793
7806
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-[11px] text-white/20", children: "Erst Workspace importieren um Tags zu verwalten." })
7794
7807
  ] }) }),
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) }),
7808
+ activeTab === "history" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HistoryPanel, { history, currentResultId: _optionalChain([currentResult, 'optionalAccess', _257 => _257.id]) || null, onSelect: handleGallerySelect, onDelete: (id) => setHistory((h) => h.filter((x) => x.id !== id)), visibleCount: historyVisibleCount, onLoadMore: () => setHistoryVisibleCount((c) => c + 20) }),
7796
7809
  activeTab === "gallery" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7797
7810
  MediaLibrary,
7798
7811
  {
7799
7812
  items: galleryItems,
7800
7813
  onImport: async () => {
7801
7814
  const media = await onSelectMedia();
7802
- if (!_optionalChain([media, 'optionalAccess', _252 => _252.length])) return;
7815
+ if (!_optionalChain([media, 'optionalAccess', _258 => _258.length])) return;
7803
7816
  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]);
7804
7817
  },
7805
7818
  onDelete: (id) => setGalleryItems((g) => g.filter((x) => x.id !== id)),
@@ -7955,7 +7968,7 @@ function createFaStore({ contracts, descriptors, persistence, workspaceId }) {
7955
7968
  };
7956
7969
  };
7957
7970
  const applyWriteResult = (sliceId, result, savedData, signal) => {
7958
- if (_optionalChain([signal, 'optionalAccess', _253 => _253.aborted])) {
7971
+ if (_optionalChain([signal, 'optionalAccess', _259 => _259.aborted])) {
7959
7972
  patchMeta(sliceId, { saveState: "idle" });
7960
7973
  return result;
7961
7974
  }
@@ -7983,8 +7996,8 @@ function createFaStore({ contracts, descriptors, persistence, workspaceId }) {
7983
7996
  const requestId = _nullishCoalesce(externalRequestId, () => ( nextRequestId()));
7984
7997
  patchMeta(sliceId, { loadRequestId: requestId, saveState: "restoring" });
7985
7998
  const result = await persistence.load(workspaceId, descriptor, _nullishCoalesce(signal, () => ( new AbortController().signal)));
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) {
7999
+ if (_optionalChain([signal, 'optionalAccess', _260 => _260.aborted]) || _optionalChain([get, 'call', _261 => _261(), 'access', _262 => _262.meta, 'access', _263 => _263[sliceId], 'optionalAccess', _264 => _264.loadRequestId]) !== requestId) {
8000
+ if (_optionalChain([signal, 'optionalAccess', _265 => _265.aborted]) && _optionalChain([get, 'call', _266 => _266(), 'access', _267 => _267.meta, 'access', _268 => _268[sliceId], 'optionalAccess', _269 => _269.loadRequestId]) === requestId) {
7988
8001
  patchMeta(sliceId, { saveState: "idle", loadRequestId: null });
7989
8002
  }
7990
8003
  return result;
@@ -8019,7 +8032,7 @@ function createFaStore({ contracts, descriptors, persistence, workspaceId }) {
8019
8032
  },
8020
8033
  async resetSlice(sliceId, signal, options) {
8021
8034
  const contract = requireContract(sliceId);
8022
- if (get().meta[sliceId].dirty && !_optionalChain([options, 'optionalAccess', _264 => _264.confirmed])) {
8035
+ if (get().meta[sliceId].dirty && !_optionalChain([options, 'optionalAccess', _270 => _270.confirmed])) {
8023
8036
  throw new Error(`Reset for slice ${sliceId} requires confirmation while unsaved changes exist`);
8024
8037
  }
8025
8038
  const defaultData = contract.createDefault();
@@ -8072,7 +8085,7 @@ function createInMemoryWorkspacePersistence(now = () => Date.now()) {
8072
8085
  }
8073
8086
  const saved = {
8074
8087
  ...clone(slice),
8075
- revision: (_nullishCoalesce(_optionalChain([current, 'optionalAccess', _265 => _265.revision]), () => ( 0))) + 1,
8088
+ revision: (_nullishCoalesce(_optionalChain([current, 'optionalAccess', _271 => _271.revision]), () => ( 0))) + 1,
8076
8089
  updatedAt: now(),
8077
8090
  ...resetAt !== void 0 ? { resetAt } : {}
8078
8091
  };
@@ -8153,7 +8166,7 @@ function createPersistenceCoordinator({
8153
8166
  if (disposed) return;
8154
8167
  const runtime = runtimeOf(sliceId);
8155
8168
  const meta = store.getState().meta[sliceId];
8156
- if (!_optionalChain([meta, 'optionalAccess', _266 => _266.dirty])) return;
8169
+ if (!_optionalChain([meta, 'optionalAccess', _272 => _272.dirty])) return;
8157
8170
  if (meta.saveState === "restoring" || meta.saveState === "saving") {
8158
8171
  runtime.pendingSave = true;
8159
8172
  return;
@@ -8181,7 +8194,7 @@ function createPersistenceCoordinator({
8181
8194
  return {
8182
8195
  async load(sliceId) {
8183
8196
  const runtime = runtimeOf(sliceId);
8184
- _optionalChain([runtime, 'access', _267 => _267.loadController, 'optionalAccess', _268 => _268.abort, 'call', _269 => _269()]);
8197
+ _optionalChain([runtime, 'access', _273 => _273.loadController, 'optionalAccess', _274 => _274.abort, 'call', _275 => _275()]);
8185
8198
  runtime.loadController = new AbortController();
8186
8199
  const controller = runtime.loadController;
8187
8200
  try {
@@ -8209,8 +8222,8 @@ function createPersistenceCoordinator({
8209
8222
  disposed = true;
8210
8223
  for (const runtime of runtimes.values()) {
8211
8224
  clearTimer(runtime);
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()]);
8225
+ _optionalChain([runtime, 'access', _276 => _276.loadController, 'optionalAccess', _277 => _277.abort, 'call', _278 => _278()]);
8226
+ _optionalChain([runtime, 'access', _279 => _279.saveController, 'optionalAccess', _280 => _280.abort, 'call', _281 => _281()]);
8214
8227
  runtime.pendingSave = false;
8215
8228
  }
8216
8229
  runtimes.clear();
@@ -8364,9 +8377,9 @@ function hatNavigationsziele(zugehoerigkeit) {
8364
8377
  var kennung = (wert) => typeof wert === "string" && wert.trim().length > 0;
8365
8378
  var kurz = (id) => id.slice(0, 8);
8366
8379
  function zugehoerigkeitOf(item) {
8367
- const runId = _optionalChain([item, 'optionalAccess', _276 => _276.szenen, 'optionalAccess', _277 => _277.prompt_run_id]);
8380
+ const runId = _optionalChain([item, 'optionalAccess', _282 => _282.szenen, 'optionalAccess', _283 => _283.prompt_run_id]);
8368
8381
  if (!kennung(runId)) return null;
8369
- const links = _nullishCoalesce(_optionalChain([item, 'optionalAccess', _278 => _278.szenen_links]), () => ( null));
8382
+ const links = _nullishCoalesce(_optionalChain([item, 'optionalAccess', _284 => _284.szenen_links]), () => ( null));
8370
8383
  if (!links || links.prompt_run_id !== runId) {
8371
8384
  return {
8372
8385
  run: null,
@@ -8397,15 +8410,15 @@ function zugehoerigkeitOf(item) {
8397
8410
  return { run, scene, hinweis: null };
8398
8411
  }
8399
8412
  function zugehoerigkeitenOf(item) {
8400
- const szenen = _optionalChain([item, 'optionalAccess', _279 => _279.szenen]);
8413
+ const szenen = _optionalChain([item, 'optionalAccess', _285 => _285.szenen]);
8401
8414
  if (!szenen) return [];
8402
8415
  const laeufe = [];
8403
8416
  const merken = (id) => {
8404
8417
  if (kennung(id) && !laeufe.includes(id)) laeufe.push(id);
8405
8418
  };
8406
8419
  merken(szenen.prompt_run_id);
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)));
8420
+ for (const run of _nullishCoalesce(szenen.runs, () => ( []))) merken(_optionalChain([run, 'optionalAccess', _286 => _286.prompt_run_id]));
8421
+ const linkFuer = (runId) => _nullishCoalesce((_nullishCoalesce(_optionalChain([item, 'optionalAccess', _287 => _287.szenen_run_links]), () => ( []))).find((l) => l.prompt_run_id === runId), () => ( (_optionalChain([item, 'optionalAccess', _288 => _288.szenen_links]) && item.szenen_links.prompt_run_id === runId ? item.szenen_links : null)));
8409
8422
  const ergebnis = [];
8410
8423
  for (const runId of laeufe) {
8411
8424
  const z = zugehoerigkeitOf({ szenen: { prompt_run_id: runId }, szenen_links: linkFuer(runId) });
package/dist/index.mjs CHANGED
@@ -22,7 +22,7 @@ import "./chunk-FUY2OCVC.mjs";
22
22
  import "./chunk-GKLCL2VQ.mjs";
23
23
 
24
24
  // package.json
25
- var version = "10.3.5";
25
+ var version = "10.3.6";
26
26
 
27
27
  // src/hooks/useOnClickOutside.ts
28
28
  import { useEffect } from "react";
@@ -5538,7 +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
+ var FLOW_BRIDGE_PROXY_TIMEOUT_MS = 75e3;
5542
5542
  function isRecord(value) {
5543
5543
  return value !== null && typeof value === "object" && !Array.isArray(value);
5544
5544
  }
@@ -5605,15 +5605,24 @@ function createFlowBridgeClient({
5605
5605
  }
5606
5606
  return { available: true, name: bridge.name, version: bridge.version, protocol: bridge.protocol, roundTripMs };
5607
5607
  },
5608
- async connect(env, { timeoutMs = FLOW_BRIDGE_CONNECT_TIMEOUT_MS } = {}) {
5608
+ async proxy({ env, tokenSuffix, method, path }) {
5609
5609
  const started = clock();
5610
- const reply = await exchange({ op: "connect", env }, timeoutMs);
5611
- const waitedMs = Math.round(clock() - started);
5610
+ const reply = await exchange({ op: "proxy", env, tokenSuffix, method, path }, FLOW_BRIDGE_PROXY_TIMEOUT_MS);
5611
+ const roundTripMs = Math.round(clock() - started);
5612
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 };
5613
+ return { ok: false, transport: null, status: null, data: null, latencyMs: null, roundTripMs, error: noBridge(FLOW_BRIDGE_PROXY_TIMEOUT_MS) };
5614
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 };
5615
+ const ok = reply.ok === true;
5616
+ const body = isRecord(reply.body) && reply.body.encoding === "text" && typeof reply.body.data === "string" ? reply.body.data : null;
5617
+ return {
5618
+ ok,
5619
+ transport: typeof reply.transport === "string" ? reply.transport : null,
5620
+ status: nullableNumber(reply.status),
5621
+ data: ok ? body : null,
5622
+ latencyMs: nullableNumber(reply.latencyMs),
5623
+ roundTripMs,
5624
+ error: ok ? null : readError(reply.error)
5625
+ };
5617
5626
  },
5618
5627
  async request(request, { timeoutMs = requestTimeoutMs } = {}) {
5619
5628
  const started = clock();
@@ -6025,7 +6034,7 @@ function stepText(step) {
6025
6034
  }
6026
6035
  var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) => {
6027
6036
  const bridge = useMemo7(() => client ?? createFlowBridgeClient({ appVersion }), [client, appVersion]);
6028
- const [connection, setConnection] = useState26(null);
6037
+ const [access, setAccess] = useState26(null);
6029
6038
  const [steps, setSteps] = useState26([]);
6030
6039
  const [load, setLoad] = useState26(null);
6031
6040
  const [renderError, setRenderError] = useState26(null);
@@ -6036,10 +6045,10 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6036
6045
  if (!tokenSuffix) return void 0;
6037
6046
  let active = true;
6038
6047
  void (async () => {
6039
- const connected = bridge.connect ? await bridge.connect(environment) : { ok: false, error: { code: "no-bridge", message: "Bridge-Client ohne connect." }, waitedMs: 0 };
6048
+ const checked = bridge.proxy ? await bridge.proxy({ env: environment, tokenSuffix, method: "GET", path: "/api/status" }) : { ok: false, transport: null, status: null, data: null, latencyMs: null, roundTripMs: 0, error: { code: "no-bridge", message: "Bridge-Client ohne proxy." } };
6040
6049
  if (!active) return;
6041
- setConnection(connected);
6042
- if (!connected.ok) return;
6050
+ setAccess(checked);
6051
+ if (!checked.ok || checked.status !== 200) return;
6043
6052
  const result = await loadFlowApp({ bridge, environment, tokenSuffix, onStep: (next) => {
6044
6053
  if (active) setSteps(next);
6045
6054
  } });
@@ -6063,7 +6072,9 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6063
6072
  customTabs: [],
6064
6073
  apiKey: null,
6065
6074
  backendUrl: load.backendUrl,
6066
- transport: "flow-bridge"
6075
+ transport: "flow-bridge",
6076
+ bridgeEnv: environment,
6077
+ bridgeTokenSuffix: tokenSuffix
6067
6078
  }));
6068
6079
  } catch (error) {
6069
6080
  setRenderError(error instanceof Error ? error.message : String(error));
@@ -6072,8 +6083,9 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6072
6083
  root?.unmount();
6073
6084
  style.remove();
6074
6085
  };
6075
- }, [load]);
6076
- const failed = !tokenSuffix || connection !== null && !connection.ok || load !== null && !load.ok || renderError !== null;
6086
+ }, [load, environment, tokenSuffix]);
6087
+ const accessFailed = access !== null && (!access.ok || access.status !== 200);
6088
+ const failed = !tokenSuffix || accessFailed || load !== null && !load.ok || renderError !== null;
6077
6089
  return /* @__PURE__ */ jsxs28("div", { className: "fixed inset-0 bg-[#0e0e0e] flex flex-col", "data-testid": "flow-fine-art-app", children: [
6078
6090
  /* @__PURE__ */ jsxs28("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
6091
  /* @__PURE__ */ jsx30("button", { type: "button", onClick: onClose, className: "font-bold text-white/80", children: "\u2190 FlowFA" }),
@@ -6081,9 +6093,10 @@ var FlowFineArtApp = ({ environment, hfToken, appVersion, client, onClose }) =>
6081
6093
  ] }),
6082
6094
  !load?.ok && /* @__PURE__ */ jsxs28("div", { className: "flex flex-col gap-1 p-4 text-[11px] font-mono break-all", "data-testid": "flow-fine-art-app-steps", children: [
6083
6095
  !tokenSuffix && /* @__PURE__ */ jsx30("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__ */ jsx30("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__ */ jsx30("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__ */ jsx30("span", { role: "alert", className: "font-bold", style: { color: "#f87171" }, children: "App nicht gestartet \u2014 ohne Freigabe erreicht sie ihren Server nicht." }),
6096
+ tokenSuffix && !access && /* @__PURE__ */ jsx30("span", { "data-testid": "flow-fine-art-app-access", className: "text-white/60", children: `Datenzugang ${environment.toUpperCase()} wird gepr\xFCft \u2026` }),
6097
+ access && /* @__PURE__ */ jsx30("span", { "data-testid": "flow-fine-art-app-access", style: { color: accessFailed ? "#f87171" : "rgba(255,255,255,0.6)" }, children: access.ok ? `Datenzugang: GET /api/status \u2192 HTTP ${access.status} \xB7 ${access.transport ?? "kein Transport"} \xB7 ${access.roundTripMs} ms` : `Datenzugang: ${access.error?.code}: ${access.error?.message}` }),
6098
+ access?.error?.code === "not-approved" && /* @__PURE__ */ jsx30("span", { style: { color: "#fbbf24" }, children: `Extension-Popup \u201EFine-Art Flow Bridge\u201C \u2192 Fine-Art App: Datenzugang \u2192 ${environment.toUpperCase()} einschalten, dann neu starten.` }),
6099
+ accessFailed && /* @__PURE__ */ jsx30("span", { role: "alert", className: "font-bold", style: { color: "#f87171" }, children: "App nicht gestartet \u2014 ohne Datenzugang erreicht sie ihren Server nicht." }),
6087
6100
  steps.map((step) => /* @__PURE__ */ jsx30("span", { style: { color: step.error ? "#f87171" : "rgba(255,255,255,0.6)" }, children: stepText(step) }, step.file)),
6088
6101
  load && !load.ok && /* @__PURE__ */ jsx30("span", { role: "alert", className: "font-bold", style: { color: "#f87171" }, children: `App nicht gestartet \u2014 ${load.error}` })
6089
6102
  ] }),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rslsp1/fa-app-tools",
3
- "version": "10.3.5",
3
+ "version": "10.3.6",
4
4
  "description": "Shared tools and hooks for Fine Art flow apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",