@rslsp1/fa-app-tools 2.0.18 → 2.0.20

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.
@@ -93,8 +93,9 @@ async function hfBatchArchive(moves, token, summary) {
93
93
  }
94
94
  function tsFromEventPath(repoPath) {
95
95
  const filename = repoPath.split("/").pop() || "";
96
- const iso = filename.replace(/_[^_]+\.json$/, "").replace(/-/g, (m, i) => i > 7 ? ":" : m);
97
- const ts = Date.parse(iso.replace(/T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z/, "T$1:$2:$3.$4Z"));
96
+ const base = filename.replace(/_[^_]+\.json$/, "");
97
+ const iso = base.replace(/T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/, "T$1:$2:$3.$4Z");
98
+ const ts = Date.parse(iso);
98
99
  return isNaN(ts) ? 0 : ts;
99
100
  }
100
101
  async function loadHFState(namespace, token) {
@@ -24,7 +24,7 @@ import {
24
24
  setHFToken,
25
25
  tsFromEventPath,
26
26
  writeHFEvent
27
- } from "./chunk-D2WTLDI7.mjs";
27
+ } from "./chunk-I73HODO5.mjs";
28
28
  export {
29
29
  HF_TOKEN_KEY,
30
30
  getHFToken,
package/dist/index.d.mts CHANGED
@@ -584,6 +584,7 @@ interface HFStateResult {
584
584
  pendingBufferCount: number;
585
585
  eventCount: number;
586
586
  localOnlyCount: number;
587
+ confirmedEventKeys: Set<string>;
587
588
  forks: Array<{
588
589
  parentTs: number;
589
590
  childTs: number[];
@@ -613,6 +614,6 @@ declare function findTips(dag: Dag): number[];
613
614
  declare function findForks(dag: Dag): DagFork[];
614
615
  declare function topoSort(events: HFEvent[]): HFEvent[];
615
616
 
616
- declare const LIB_VERSION = "2.0.18";
617
+ declare const LIB_VERSION = "2.0.20";
617
618
 
618
619
  export { AvatarArchitectApp, type AvatarArchitectAppProps, CollapsibleCard, CompactDropdown, type DagFork, type ExtractedCharacter, FaApp, type FaAppProps, FaToolsBadge, type FlowSdk, GLOBAL_STYLES, type Generation, type HFEvent, type HFEventVersion, type HFFileInfo$1 as HFFileInfo, type HFMetadataEntry, type HFStateMeta, type HFStateResult, type HFStateSnapshot, HistoryPanel, type ImageAddedPayload, InspectPanel, LIB_VERSION, LabBlend, LabCompare, type LabFrame, LabImagePicker, type LabItem, LabLoop, LabRemix, type LabServices, LabsTab, ListView, type MediaItem, MediaLibrary, type MetadataUpdatedPayload, PillButton, type ProjectMeta, type ProjectSettings, ProjectSyncTab, PromptTab, SectionLabel, type SelectedLabImage, type SelectedTag, SetupPanel, type SyncDiff, TagManagerPanel, type TagOption, type TagUpsertedPayload, type WorkspaceTags, applyEvent, applyEvents, autoLabel, buildBlendInstruction, buildCompareInstruction, buildDag, buildFallbackPrompt, buildGenerationPrompt, buildImageGenerationOptions, buildLoopInstruction, buildPromptTabPayload, buildReferenceImageMediaIds, buildRemixInstruction, buildScanInstruction, cleanAiResponse, createFlowServices, exportProjectToZip, findForks, findTips, formatTreeToMarkdown, frameToGeneration, getFormattedTimestamp, getHFToken, getSessionClientId, groupGenerationsToLabItems, hfBatchArchive, hfBootstrapFromLegacy, hfDeleteProject, hfDownloadProject, hfListDir, hfListProjects, hfLoadImageAsBase64, hfUploadImage, hfUploadProjectForm, hfUploadSmallFile, importProjectFromZip, injectXMPMetadata, interpretSdkError, loadHFState, loadPendingEvents, parsePromptFile, parsePromptResponse, setHFToken, topoSort, tsFromEventPath, useHFState, useKeyboardNavigation, useOnClickOutside, writeHFEvent };
package/dist/index.d.ts CHANGED
@@ -584,6 +584,7 @@ interface HFStateResult {
584
584
  pendingBufferCount: number;
585
585
  eventCount: number;
586
586
  localOnlyCount: number;
587
+ confirmedEventKeys: Set<string>;
587
588
  forks: Array<{
588
589
  parentTs: number;
589
590
  childTs: number[];
@@ -613,6 +614,6 @@ declare function findTips(dag: Dag): number[];
613
614
  declare function findForks(dag: Dag): DagFork[];
614
615
  declare function topoSort(events: HFEvent[]): HFEvent[];
615
616
 
616
- declare const LIB_VERSION = "2.0.18";
617
+ declare const LIB_VERSION = "2.0.20";
617
618
 
618
619
  export { AvatarArchitectApp, type AvatarArchitectAppProps, CollapsibleCard, CompactDropdown, type DagFork, type ExtractedCharacter, FaApp, type FaAppProps, FaToolsBadge, type FlowSdk, GLOBAL_STYLES, type Generation, type HFEvent, type HFEventVersion, type HFFileInfo$1 as HFFileInfo, type HFMetadataEntry, type HFStateMeta, type HFStateResult, type HFStateSnapshot, HistoryPanel, type ImageAddedPayload, InspectPanel, LIB_VERSION, LabBlend, LabCompare, type LabFrame, LabImagePicker, type LabItem, LabLoop, LabRemix, type LabServices, LabsTab, ListView, type MediaItem, MediaLibrary, type MetadataUpdatedPayload, PillButton, type ProjectMeta, type ProjectSettings, ProjectSyncTab, PromptTab, SectionLabel, type SelectedLabImage, type SelectedTag, SetupPanel, type SyncDiff, TagManagerPanel, type TagOption, type TagUpsertedPayload, type WorkspaceTags, applyEvent, applyEvents, autoLabel, buildBlendInstruction, buildCompareInstruction, buildDag, buildFallbackPrompt, buildGenerationPrompt, buildImageGenerationOptions, buildLoopInstruction, buildPromptTabPayload, buildReferenceImageMediaIds, buildRemixInstruction, buildScanInstruction, cleanAiResponse, createFlowServices, exportProjectToZip, findForks, findTips, formatTreeToMarkdown, frameToGeneration, getFormattedTimestamp, getHFToken, getSessionClientId, groupGenerationsToLabItems, hfBatchArchive, hfBootstrapFromLegacy, hfDeleteProject, hfDownloadProject, hfListDir, hfListProjects, hfLoadImageAsBase64, hfUploadImage, hfUploadProjectForm, hfUploadSmallFile, importProjectFromZip, injectXMPMetadata, interpretSdkError, loadHFState, loadPendingEvents, parsePromptFile, parsePromptResponse, setHFToken, topoSort, tsFromEventPath, useHFState, useKeyboardNavigation, useOnClickOutside, writeHFEvent };
package/dist/index.js CHANGED
@@ -381,8 +381,9 @@ async function hfBatchArchive(moves, token, summary) {
381
381
  }
382
382
  function tsFromEventPath(repoPath) {
383
383
  const filename = repoPath.split("/").pop() || "";
384
- const iso = filename.replace(/_[^_]+\.json$/, "").replace(/-/g, (m, i) => i > 7 ? ":" : m);
385
- const ts = Date.parse(iso.replace(/T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z/, "T$1:$2:$3.$4Z"));
384
+ const base = filename.replace(/_[^_]+\.json$/, "");
385
+ const iso = base.replace(/T(\d{2})-(\d{2})-(\d{2})-(\d{3})Z$/, "T$1:$2:$3.$4Z");
386
+ const ts = Date.parse(iso);
386
387
  return isNaN(ts) ? 0 : ts;
387
388
  }
388
389
  async function loadHFState(namespace, token) {
@@ -2738,6 +2739,7 @@ function useHFState(token, namespace) {
2738
2739
  error,
2739
2740
  pendingBufferCount,
2740
2741
  localOnlyCount,
2742
+ confirmedEventKeys: knownEventPaths.current,
2741
2743
  eventCount,
2742
2744
  forks,
2743
2745
  writeEvent,
@@ -4126,33 +4128,74 @@ var EVENT_TYPE_COLORS = {
4126
4128
  metadata_updated: "#34d399",
4127
4129
  probe: "#fbbf24"
4128
4130
  };
4129
- function EventMonitor({ events }) {
4131
+ function EventMonitor({ events, confirmedEventKeys, galleryItems, imageUploadStatus }) {
4130
4132
  if (!events.length) {
4131
4133
  return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { padding: "12px 14px", fontSize: 12, color: "rgba(255,255,255,0.3)", fontStyle: "italic" }, children: "Noch keine Events geladen." });
4132
4134
  }
4133
4135
  const sorted = [...events].sort((a, b) => b.ts - a.ts).slice(0, 30);
4134
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "8px 10px 4px" }, children: [
4136
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "6px 8px 4px" }, children: [
4135
4137
  sorted.map((e, i) => {
4136
- const color = EVENT_TYPE_COLORS[e.type] || "rgba(255,255,255,0.5)";
4138
+ const eKey = `${e.ts}_${e.clientId}`;
4139
+ const isConfirmed = confirmedEventKeys.has(eKey);
4140
+ const typeColor = EVENT_TYPE_COLORS[e.type] || "rgba(255,255,255,0.5)";
4137
4141
  const date = new Date(e.ts);
4138
4142
  const timeStr = date.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit", second: "2-digit" });
4139
- const clientShort = e.clientId?.slice(0, 8) ?? "?";
4143
+ const isImageEvent = e.type === "image_added";
4144
+ const imgId = isImageEvent ? e.payload?.id : void 0;
4145
+ const galleryItem = imgId ? galleryItems.find((g) => g.id === imgId) : void 0;
4146
+ const uploadStatus = imgId ? imageUploadStatus.get(imgId) : void 0;
4140
4147
  const payloadStr = JSON.stringify(e.payload ?? {});
4141
- const payloadPreview = payloadStr.length > 80 ? payloadStr.slice(0, 80) + "\u2026" : payloadStr;
4142
- return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "flex-start", padding: "5px 0", borderBottom: "1px solid rgba(255,255,255,0.04)" }, children: [
4143
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", minWidth: 60, paddingTop: 2, fontVariantNumeric: "tabular-nums" }, children: timeStr }),
4144
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color, minWidth: 120, flexShrink: 0 }, children: e.type }),
4145
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.2)", minWidth: 65, flexShrink: 0, fontFamily: "monospace" }, children: clientShort }),
4146
- /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: payloadPreview })
4147
- ] }, `${e.ts}_${e.clientId}_${i}`);
4148
+ const payloadPreview = payloadStr.length > 70 ? payloadStr.slice(0, 70) + "\u2026" : payloadStr;
4149
+ return /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", gap: 7, alignItems: "flex-start", padding: "6px 2px", borderBottom: "1px solid rgba(255,255,255,0.05)" }, children: [
4150
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { width: 36, height: 36, flexShrink: 0, borderRadius: 4, overflow: "hidden", background: "rgba(255,255,255,0.05)", display: "flex", alignItems: "center", justifyContent: "center" }, children: isImageEvent ? galleryItem?.base64 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("img", { src: galleryItem.base64, style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 18, color: "rgba(255,255,255,0.2)" }, children: "image" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16, color: "rgba(255,255,255,0.15)" }, children: e.type === "tag_upserted" ? "label" : e.type === "metadata_updated" ? "edit_note" : "data_object" }) }),
4151
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
4152
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }, children: [
4153
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 11, fontWeight: 700, color: typeColor }, children: e.type }),
4154
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", fontVariantNumeric: "tabular-nums" }, children: timeStr }),
4155
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { flex: 1 } }),
4156
+ isConfirmed ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 9, fontWeight: 700, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4157
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "check_circle" }),
4158
+ "HF"
4159
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 9, fontWeight: 700, color: "#fbbf24", display: "flex", alignItems: "center", gap: 2 }, children: [
4160
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "schedule" }),
4161
+ "lokal"
4162
+ ] })
4163
+ ] }),
4164
+ isImageEvent && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }, children: [
4165
+ uploadStatus === "done" && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 9, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
4166
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_done" }),
4167
+ "Bild auf HF"
4168
+ ] }),
4169
+ uploadStatus === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 9, color: "#60a5fa", display: "flex", alignItems: "center", gap: 2 }, children: [
4170
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_upload" }),
4171
+ "Bild l\xE4dt\u2026"
4172
+ ] }),
4173
+ uploadStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 9, color: "#f87171", display: "flex", alignItems: "center", gap: 2 }, children: [
4174
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_off" }),
4175
+ "Bild-Upload fehlgeschlagen"
4176
+ ] }),
4177
+ !uploadStatus && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.2)" }, children: "Bild-Upload unbekannt (anderes Ger\xE4t?)" }),
4178
+ galleryItem?.base64 ? /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 9, color: "#4ade80", marginLeft: 6, display: "flex", alignItems: "center", gap: 2 }, children: [
4179
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "photo" }),
4180
+ "lokal vorhanden"
4181
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { style: { fontSize: 9, color: "#f87171", marginLeft: 6, display: "flex", alignItems: "center", gap: 2 }, children: [
4182
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "broken_image" }),
4183
+ "kein lokales Bild"
4184
+ ] })
4185
+ ] }),
4186
+ /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: payloadPreview })
4187
+ ] })
4188
+ ] }, `${eKey}_${i}`);
4148
4189
  }),
4149
4190
  /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { style: { padding: "6px 0 2px", fontSize: 9, color: "rgba(255,255,255,0.2)", textAlign: "right" }, children: [
4150
4191
  events.length,
4151
- " Events gesamt"
4192
+ " Events gesamt \xB7 ",
4193
+ [...confirmedEventKeys].length,
4194
+ " auf HF best\xE4tigt"
4152
4195
  ] })
4153
4196
  ] });
4154
4197
  }
4155
- function HFTestTab({ token, namespace, galleryItems, allEvents = [] }) {
4198
+ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEventKeys = /* @__PURE__ */ new Set(), imageUploadStatus = /* @__PURE__ */ new Map() }) {
4156
4199
  const [selected, setSelected] = (0, import_react22.useState)(null);
4157
4200
  const [results, setResults] = (0, import_react22.useState)({});
4158
4201
  const [expanded, setExpanded] = (0, import_react22.useState)({});
@@ -4211,7 +4254,15 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [] }) {
4211
4254
  title: "Event Monitor",
4212
4255
  icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "bolt" }),
4213
4256
  defaultOpen: true,
4214
- children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(EventMonitor, { events: allEvents })
4257
+ children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
4258
+ EventMonitor,
4259
+ {
4260
+ events: allEvents,
4261
+ confirmedEventKeys,
4262
+ galleryItems,
4263
+ imageUploadStatus
4264
+ }
4265
+ )
4215
4266
  }
4216
4267
  ) }),
4217
4268
  /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
@@ -4368,10 +4419,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4368
4419
  localOnlyCount,
4369
4420
  eventCount,
4370
4421
  allEvents: hfAllEvents,
4422
+ confirmedEventKeys: hfConfirmedKeys,
4371
4423
  writeEvent: hfWriteEvent,
4372
4424
  refresh: refreshHF,
4373
4425
  hasStateZip
4374
4426
  } = useHFState(hfToken, effectiveNamespace);
4427
+ const [imageUploadStatus, setImageUploadStatus] = (0, import_react23.useState)(/* @__PURE__ */ new Map());
4375
4428
  const [bootstrapLog, setBootstrapLog] = (0, import_react23.useState)([]);
4376
4429
  const [isBootstrapping, setIsBootstrapping] = (0, import_react23.useState)(false);
4377
4430
  const syncTopSlot = /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
@@ -4733,8 +4786,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4733
4786
  });
4734
4787
  console.log("[HF] handleGenerateImage \u2014 condition check:", { hfToken: !!hfToken, base64: !!base64, effectiveNamespace });
4735
4788
  if (hfToken && base64 && effectiveNamespace) {
4736
- hfUploadImage(base64, genId, hfToken).catch((e) => {
4789
+ setImageUploadStatus((m) => new Map(m).set(genId, "uploading"));
4790
+ hfUploadImage(base64, genId, hfToken).then(() => setImageUploadStatus((m) => new Map(m).set(genId, "done"))).catch((e) => {
4737
4791
  console.error("[HF] hfUploadImage failed:", e);
4792
+ setImageUploadStatus((m) => new Map(m).set(genId, "failed"));
4738
4793
  });
4739
4794
  const entry = {
4740
4795
  id: genId,
@@ -5561,7 +5616,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
5561
5616
  onTagMove: handleTagMove
5562
5617
  }
5563
5618
  ),
5564
- activeTab === "hftest" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(HFTestTab, { token: hfToken, namespace: effectiveNamespace, galleryItems, allEvents: hfAllEvents }) })
5619
+ activeTab === "hftest" && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "absolute inset-0", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
5620
+ HFTestTab,
5621
+ {
5622
+ token: hfToken,
5623
+ namespace: effectiveNamespace,
5624
+ galleryItems,
5625
+ allEvents: hfAllEvents,
5626
+ confirmedEventKeys: hfConfirmedKeys,
5627
+ imageUploadStatus
5628
+ }
5629
+ ) })
5565
5630
  ] })
5566
5631
  ] }),
5567
5632
  /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "flex border-t border-white/10 bg-black shrink-0", style: { height: 56, paddingBottom: "env(safe-area-inset-bottom, 0px)" }, children: [
@@ -5943,7 +6008,7 @@ function FaApp({
5943
6008
  // src/index.ts
5944
6009
  init_hfStateService();
5945
6010
  init_hfStateService();
5946
- var LIB_VERSION = "2.0.18";
6011
+ var LIB_VERSION = "2.0.20";
5947
6012
  // Annotate the CommonJS export names for ESM import in node:
5948
6013
  0 && (module.exports = {
5949
6014
  AvatarArchitectApp,
package/dist/index.mjs CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  setHFToken,
22
22
  tsFromEventPath,
23
23
  writeHFEvent
24
- } from "./chunk-D2WTLDI7.mjs";
24
+ } from "./chunk-I73HODO5.mjs";
25
25
 
26
26
  // src/hooks/useOnClickOutside.ts
27
27
  import { useEffect } from "react";
@@ -1598,7 +1598,7 @@ var ProjectSyncTab = ({
1598
1598
  {
1599
1599
  onClick: async () => {
1600
1600
  try {
1601
- const { hfDownloadProject: hfDownloadProject2 } = await import("./hfStateService-OAECMP4M.mjs");
1601
+ const { hfDownloadProject: hfDownloadProject2 } = await import("./hfStateService-PDBVLFML.mjs");
1602
1602
  const file = await hfDownloadProject2(p.path, hfToken);
1603
1603
  onHfLoad(file);
1604
1604
  } catch (e) {
@@ -2070,6 +2070,7 @@ function useHFState(token, namespace) {
2070
2070
  error,
2071
2071
  pendingBufferCount,
2072
2072
  localOnlyCount,
2073
+ confirmedEventKeys: knownEventPaths.current,
2073
2074
  eventCount,
2074
2075
  forks,
2075
2076
  writeEvent,
@@ -3458,33 +3459,74 @@ var EVENT_TYPE_COLORS = {
3458
3459
  metadata_updated: "#34d399",
3459
3460
  probe: "#fbbf24"
3460
3461
  };
3461
- function EventMonitor({ events }) {
3462
+ function EventMonitor({ events, confirmedEventKeys, galleryItems, imageUploadStatus }) {
3462
3463
  if (!events.length) {
3463
3464
  return /* @__PURE__ */ jsx20("div", { style: { padding: "12px 14px", fontSize: 12, color: "rgba(255,255,255,0.3)", fontStyle: "italic" }, children: "Noch keine Events geladen." });
3464
3465
  }
3465
3466
  const sorted = [...events].sort((a, b) => b.ts - a.ts).slice(0, 30);
3466
- return /* @__PURE__ */ jsxs18("div", { style: { padding: "8px 10px 4px" }, children: [
3467
+ return /* @__PURE__ */ jsxs18("div", { style: { padding: "6px 8px 4px" }, children: [
3467
3468
  sorted.map((e, i) => {
3468
- const color = EVENT_TYPE_COLORS[e.type] || "rgba(255,255,255,0.5)";
3469
+ const eKey = `${e.ts}_${e.clientId}`;
3470
+ const isConfirmed = confirmedEventKeys.has(eKey);
3471
+ const typeColor = EVENT_TYPE_COLORS[e.type] || "rgba(255,255,255,0.5)";
3469
3472
  const date = new Date(e.ts);
3470
3473
  const timeStr = date.toLocaleTimeString("de-DE", { hour: "2-digit", minute: "2-digit", second: "2-digit" });
3471
- const clientShort = e.clientId?.slice(0, 8) ?? "?";
3474
+ const isImageEvent = e.type === "image_added";
3475
+ const imgId = isImageEvent ? e.payload?.id : void 0;
3476
+ const galleryItem = imgId ? galleryItems.find((g) => g.id === imgId) : void 0;
3477
+ const uploadStatus = imgId ? imageUploadStatus.get(imgId) : void 0;
3472
3478
  const payloadStr = JSON.stringify(e.payload ?? {});
3473
- const payloadPreview = payloadStr.length > 80 ? payloadStr.slice(0, 80) + "\u2026" : payloadStr;
3474
- return /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: 8, alignItems: "flex-start", padding: "5px 0", borderBottom: "1px solid rgba(255,255,255,0.04)" }, children: [
3475
- /* @__PURE__ */ jsx20("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", minWidth: 60, paddingTop: 2, fontVariantNumeric: "tabular-nums" }, children: timeStr }),
3476
- /* @__PURE__ */ jsx20("span", { style: { fontSize: 11, fontWeight: 700, color, minWidth: 120, flexShrink: 0 }, children: e.type }),
3477
- /* @__PURE__ */ jsx20("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.2)", minWidth: 65, flexShrink: 0, fontFamily: "monospace" }, children: clientShort }),
3478
- /* @__PURE__ */ jsx20("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.35)", flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: payloadPreview })
3479
- ] }, `${e.ts}_${e.clientId}_${i}`);
3479
+ const payloadPreview = payloadStr.length > 70 ? payloadStr.slice(0, 70) + "\u2026" : payloadStr;
3480
+ return /* @__PURE__ */ jsxs18("div", { style: { display: "flex", gap: 7, alignItems: "flex-start", padding: "6px 2px", borderBottom: "1px solid rgba(255,255,255,0.05)" }, children: [
3481
+ /* @__PURE__ */ jsx20("div", { style: { width: 36, height: 36, flexShrink: 0, borderRadius: 4, overflow: "hidden", background: "rgba(255,255,255,0.05)", display: "flex", alignItems: "center", justifyContent: "center" }, children: isImageEvent ? galleryItem?.base64 ? /* @__PURE__ */ jsx20("img", { src: galleryItem.base64, style: { width: "100%", height: "100%", objectFit: "cover" } }) : /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 18, color: "rgba(255,255,255,0.2)" }, children: "image" }) : /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 16, color: "rgba(255,255,255,0.15)" }, children: e.type === "tag_upserted" ? "label" : e.type === "metadata_updated" ? "edit_note" : "data_object" }) }),
3482
+ /* @__PURE__ */ jsxs18("div", { style: { flex: 1, minWidth: 0 }, children: [
3483
+ /* @__PURE__ */ jsxs18("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }, children: [
3484
+ /* @__PURE__ */ jsx20("span", { style: { fontSize: 11, fontWeight: 700, color: typeColor }, children: e.type }),
3485
+ /* @__PURE__ */ jsx20("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", fontVariantNumeric: "tabular-nums" }, children: timeStr }),
3486
+ /* @__PURE__ */ jsx20("div", { style: { flex: 1 } }),
3487
+ isConfirmed ? /* @__PURE__ */ jsxs18("span", { style: { fontSize: 9, fontWeight: 700, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
3488
+ /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "check_circle" }),
3489
+ "HF"
3490
+ ] }) : /* @__PURE__ */ jsxs18("span", { style: { fontSize: 9, fontWeight: 700, color: "#fbbf24", display: "flex", alignItems: "center", gap: 2 }, children: [
3491
+ /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "schedule" }),
3492
+ "lokal"
3493
+ ] })
3494
+ ] }),
3495
+ isImageEvent && /* @__PURE__ */ jsxs18("div", { style: { display: "flex", alignItems: "center", gap: 6, marginBottom: 3 }, children: [
3496
+ uploadStatus === "done" && /* @__PURE__ */ jsxs18("span", { style: { fontSize: 9, color: "#4ade80", display: "flex", alignItems: "center", gap: 2 }, children: [
3497
+ /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_done" }),
3498
+ "Bild auf HF"
3499
+ ] }),
3500
+ uploadStatus === "uploading" && /* @__PURE__ */ jsxs18("span", { style: { fontSize: 9, color: "#60a5fa", display: "flex", alignItems: "center", gap: 2 }, children: [
3501
+ /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_upload" }),
3502
+ "Bild l\xE4dt\u2026"
3503
+ ] }),
3504
+ uploadStatus === "failed" && /* @__PURE__ */ jsxs18("span", { style: { fontSize: 9, color: "#f87171", display: "flex", alignItems: "center", gap: 2 }, children: [
3505
+ /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "cloud_off" }),
3506
+ "Bild-Upload fehlgeschlagen"
3507
+ ] }),
3508
+ !uploadStatus && /* @__PURE__ */ jsx20("span", { style: { fontSize: 9, color: "rgba(255,255,255,0.2)" }, children: "Bild-Upload unbekannt (anderes Ger\xE4t?)" }),
3509
+ galleryItem?.base64 ? /* @__PURE__ */ jsxs18("span", { style: { fontSize: 9, color: "#4ade80", marginLeft: 6, display: "flex", alignItems: "center", gap: 2 }, children: [
3510
+ /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "photo" }),
3511
+ "lokal vorhanden"
3512
+ ] }) : /* @__PURE__ */ jsxs18("span", { style: { fontSize: 9, color: "#f87171", marginLeft: 6, display: "flex", alignItems: "center", gap: 2 }, children: [
3513
+ /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 11 }, children: "broken_image" }),
3514
+ "kein lokales Bild"
3515
+ ] })
3516
+ ] }),
3517
+ /* @__PURE__ */ jsx20("div", { style: { fontSize: 9, color: "rgba(255,255,255,0.25)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }, children: payloadPreview })
3518
+ ] })
3519
+ ] }, `${eKey}_${i}`);
3480
3520
  }),
3481
3521
  /* @__PURE__ */ jsxs18("div", { style: { padding: "6px 0 2px", fontSize: 9, color: "rgba(255,255,255,0.2)", textAlign: "right" }, children: [
3482
3522
  events.length,
3483
- " Events gesamt"
3523
+ " Events gesamt \xB7 ",
3524
+ [...confirmedEventKeys].length,
3525
+ " auf HF best\xE4tigt"
3484
3526
  ] })
3485
3527
  ] });
3486
3528
  }
3487
- function HFTestTab({ token, namespace, galleryItems, allEvents = [] }) {
3529
+ function HFTestTab({ token, namespace, galleryItems, allEvents = [], confirmedEventKeys = /* @__PURE__ */ new Set(), imageUploadStatus = /* @__PURE__ */ new Map() }) {
3488
3530
  const [selected, setSelected] = useState15(null);
3489
3531
  const [results, setResults] = useState15({});
3490
3532
  const [expanded, setExpanded] = useState15({});
@@ -3543,7 +3585,15 @@ function HFTestTab({ token, namespace, galleryItems, allEvents = [] }) {
3543
3585
  title: "Event Monitor",
3544
3586
  icon: /* @__PURE__ */ jsx20("span", { className: "material-symbols-outlined", style: { fontSize: 16 }, children: "bolt" }),
3545
3587
  defaultOpen: true,
3546
- children: /* @__PURE__ */ jsx20(EventMonitor, { events: allEvents })
3588
+ children: /* @__PURE__ */ jsx20(
3589
+ EventMonitor,
3590
+ {
3591
+ events: allEvents,
3592
+ confirmedEventKeys,
3593
+ galleryItems,
3594
+ imageUploadStatus
3595
+ }
3596
+ )
3547
3597
  }
3548
3598
  ) }),
3549
3599
  /* @__PURE__ */ jsx20(
@@ -3700,10 +3750,12 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
3700
3750
  localOnlyCount,
3701
3751
  eventCount,
3702
3752
  allEvents: hfAllEvents,
3753
+ confirmedEventKeys: hfConfirmedKeys,
3703
3754
  writeEvent: hfWriteEvent,
3704
3755
  refresh: refreshHF,
3705
3756
  hasStateZip
3706
3757
  } = useHFState(hfToken, effectiveNamespace);
3758
+ const [imageUploadStatus, setImageUploadStatus] = useState16(/* @__PURE__ */ new Map());
3707
3759
  const [bootstrapLog, setBootstrapLog] = useState16([]);
3708
3760
  const [isBootstrapping, setIsBootstrapping] = useState16(false);
3709
3761
  const syncTopSlot = /* @__PURE__ */ jsxs19(Fragment9, { children: [
@@ -4065,8 +4117,10 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4065
4117
  });
4066
4118
  console.log("[HF] handleGenerateImage \u2014 condition check:", { hfToken: !!hfToken, base64: !!base64, effectiveNamespace });
4067
4119
  if (hfToken && base64 && effectiveNamespace) {
4068
- hfUploadImage(base64, genId, hfToken).catch((e) => {
4120
+ setImageUploadStatus((m) => new Map(m).set(genId, "uploading"));
4121
+ hfUploadImage(base64, genId, hfToken).then(() => setImageUploadStatus((m) => new Map(m).set(genId, "done"))).catch((e) => {
4069
4122
  console.error("[HF] hfUploadImage failed:", e);
4123
+ setImageUploadStatus((m) => new Map(m).set(genId, "failed"));
4070
4124
  });
4071
4125
  const entry = {
4072
4126
  id: genId,
@@ -4550,7 +4604,7 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4550
4604
  onClick: async () => {
4551
4605
  setIsLoadingFromHF(true);
4552
4606
  try {
4553
- const { hfListProjects: hfListProjects2, hfDownloadProject: hfDownloadProject2 } = await import("./hfStateService-OAECMP4M.mjs");
4607
+ const { hfListProjects: hfListProjects2, hfDownloadProject: hfDownloadProject2 } = await import("./hfStateService-PDBVLFML.mjs");
4554
4608
  const projects = await hfListProjects2(hfToken);
4555
4609
  if (projects.length > 0) {
4556
4610
  const file = await hfDownloadProject2(projects[0].path, hfToken);
@@ -4893,7 +4947,17 @@ function AvatarArchitectApp({ onGenerateImage, onGeneratePrompt, onDownload, onS
4893
4947
  onTagMove: handleTagMove
4894
4948
  }
4895
4949
  ),
4896
- activeTab === "hftest" && /* @__PURE__ */ jsx21("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx21(HFTestTab, { token: hfToken, namespace: effectiveNamespace, galleryItems, allEvents: hfAllEvents }) })
4950
+ activeTab === "hftest" && /* @__PURE__ */ jsx21("div", { className: "absolute inset-0", children: /* @__PURE__ */ jsx21(
4951
+ HFTestTab,
4952
+ {
4953
+ token: hfToken,
4954
+ namespace: effectiveNamespace,
4955
+ galleryItems,
4956
+ allEvents: hfAllEvents,
4957
+ confirmedEventKeys: hfConfirmedKeys,
4958
+ imageUploadStatus
4959
+ }
4960
+ ) })
4897
4961
  ] })
4898
4962
  ] }),
4899
4963
  /* @__PURE__ */ jsx21("div", { className: "flex border-t border-white/10 bg-black shrink-0", style: { height: 56, paddingBottom: "env(safe-area-inset-bottom, 0px)" }, children: [
@@ -5273,7 +5337,7 @@ function FaApp({
5273
5337
  }
5274
5338
 
5275
5339
  // src/index.ts
5276
- var LIB_VERSION = "2.0.18";
5340
+ var LIB_VERSION = "2.0.20";
5277
5341
  export {
5278
5342
  AvatarArchitectApp,
5279
5343
  CollapsibleCard,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rslsp1/fa-app-tools",
3
- "version": "2.0.18",
3
+ "version": "2.0.20",
4
4
  "description": "Shared tools and hooks for Fine Art flow apps",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",