MediaWiki:Gadget-LabelScanIndexer.js: Unterschied zwischen den Versionen

Keine Bearbeitungszusammenfassung
Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
/* Gadget: LabelScanIndexer (Auto-Save)
/* Gadget: LabelScanIndexer (Auto-Save)
* Läuft nur auf der Seite "Hilfe:LabelScan-Indexer" (Namespace Help = 12)
  * Erzeugt Embeddings lokal (CLIP) und speichert in MediaWiki:Gadget-LabelScan-index.json
  * Erzeugt Embeddings lokal (CLIP) und speichert in MediaWiki:Gadget-LabelScan-index.json
* Läuft nur auf der Seite "Hilfe:LabelScan-Indexer"
  */
  */


/* global mw */
/* global mw */
(function () {
(function () {
   // ---------- Seitenerkennung (robust) ----------
   'use strict';
  const NS = mw.config.get('wgNamespaceNumber'); // 12 = Help/Hilfe
  const TITLE = mw.config.get('wgTitle');        // nur der Titel ohne Namespace


   if (!(NS === 12 && TITLE === 'LabelScan-Indexer')) {
   // ---------- Seitenerkennung (im IIFE, also return ist erlaubt) ----------
     // Debug-Hinweis, falls du auf der falschen Seite testest
  const NS = mw.config.get('wgNamespaceNumber'); // 12 = Hilfe/Help
  const TITLE = mw.config.get('wgTitle');        // Titel ohne Namespace
  const ON_PAGE = (NS === 12 && TITLE === 'LabelScan-Indexer');
  if (!ON_PAGE) {
     // Nur debuggen, kein Top-Level return außerhalb einer Funktion
     // console.debug('[LabelScanIndexer] nicht aktiv auf', NS, TITLE);
     // console.debug('[LabelScanIndexer] nicht aktiv auf', NS, TITLE);
     return;
     return;
Zeile 90: Zeile 92:
       // mod.env.backends.onnx.preferredBackend = 'webgpu';
       // mod.env.backends.onnx.preferredBackend = 'webgpu';


       // WASM-Runtime-Pfade
       // WASM-Runtime-Pfad
       mod.env.backends = mod.env.backends || {};
       mod.env.backends = mod.env.backends || {};
       mod.env.backends.onnx = mod.env.backends.onnx || {};
       mod.env.backends.onnx = mod.env.backends.onnx || {};
Zeile 155: Zeile 157:
   if (!runBtn) {
   if (!runBtn) {
     console.warn('[LabelScanIndexer] Button #idx-run nicht gefunden – ist das HTML auf der Seite eingebunden?');
     console.warn('[LabelScanIndexer] Button #idx-run nicht gefunden – ist das HTML auf der Seite eingebunden?');
     return;
  } else {
  }
     runBtn.addEventListener('click', async () => {
      try {
        if (!hasInterfaceRight()) {
          alert('⚠️ Du brauchst Admin/Interface-Rechte (editinterface).');
          return;
        }


  runBtn.addEventListener('click', async () => {
        const titleEl = $('idx-title');
    try {
        const thumbEl = $('idx-thumb');
      if (!hasInterfaceRight()) {
         const fileEl  = $('idx-file');
         alert('⚠️ Du brauchst Admin/Interface-Rechte (editinterface).');
        return;
      }


      const title = $('idx-title')?.value.trim();
        const title = titleEl ? titleEl.value.trim() : '';
      const thumb = $('idx-thumb')?.value.trim();
        const thumb = thumbEl ? thumbEl.value.trim() : '';
      const file = $('idx-file')?.files?.[0];
        const file = fileEl?.files?.[0];


      if (!title) return alert('Titel fehlt.');
        if (!title) { alert('Titel fehlt.'); return; }
      if (!file) return alert('Bitte eine Bilddatei wählen.');
        if (!file) { alert('Bitte eine Bilddatei wählen.'); return; }


      runBtn.disabled = true;
        runBtn.disabled = true;


      status('Embedding berechnen …');
        status('Embedding berechnen …');
      const vec = await buildEmbeddingFromFile(file);
        const vec = await buildEmbeddingFromFile(file);
      const b64 = float32ToBase64(vec);
        const b64 = float32ToBase64(vec);


      $('idx-out').value = JSON.stringify({ title, thumb, embed: b64 }, null, 2);
        const outBox = $('idx-out');
        if (outBox) outBox.value = JSON.stringify({ title, thumb, embed: b64 }, null, 2);


      status('Index laden …');
        status('Index laden …');
      const arr = await fetchIndexJSON();
        const arr = await fetchIndexJSON();
      arr.push({ title, thumb, embed: b64 });
        arr.push({ title, thumb, embed: b64 });


      status('Speichern …');
        status('Speichern …');
      await saveIndexJSON(arr, `LabelScan: +1 embedding für "${title}"`);
        await saveIndexJSON(arr, `LabelScan: +1 embedding für "${title}"`);


      status('Gespeichert ✅');
        status('Gespeichert ✅');
    } catch (e) {
      } catch (e) {
      console.error(e);
        console.error(e);
      status('Fehler ❌ ' + (e?.message || e));
        status('Fehler ❌ ' + (e?.message || e));
      alert('Fehler: ' + (e?.message || e));
        alert('Fehler: ' + (e?.message || e));
    } finally {
      } finally {
      runBtn.disabled = false;
        runBtn.disabled = false;
     }
      }
   });
     });
   }


   console.log('[LabelScanIndexer] bereit');
   console.log('[LabelScanIndexer] bereit');
})();
})();