hmgr 0.0.21 → 0.0.22

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/gui/main.js CHANGED
@@ -13,7 +13,7 @@ import { fileURLToPath } from 'node:url';
13
13
  import { bauen, umgebungLesen } from "../cli/main.js";
14
14
  import { quelleAlsText, quelleAusText } from "../adapter/quelle-text.js";
15
15
  import { paketVersion } from "../adapter/paket-version.js";
16
- import { infoPlistPfad, neuereVersionAufPlatte } from "./selbst-update.js";
16
+ import { infoPlistPfad, MeldungsPuffer, neuereVersionAufPlatte } from "./selbst-update.js";
17
17
  import { quelleName, quelleSchluessel } from "../kern/modell.js";
18
18
  import { kannProfile } from "../ports/harness.js";
19
19
  import { iconFuerQuelle } from "./icons.js";
@@ -28,6 +28,8 @@ const smoketest = process.env.HMGR_GUI_SMOKETEST === '1';
28
28
  // E84 Teil 1: Pfad eines im Fixture noch unbekannten Verzeichnisses, das der Smoke-Lauf per Dialog
29
29
  // hinzufügt, um den Sprung zur neuen Karte zu belegen. Nur zur Konstruktionszeit des DOM-Auszug-
30
30
  // Skripts gelesen (Node-Seite), nicht zur Laufzeit im Renderer.
31
+ /** E90-Nachtrag: Smoke-Lauf, in dem die Platten-Erkennung schon vor dem Laden der Seite feuert. */
32
+ const smoketestFrueh = process.env.HMGR_GUI_SMOKE_FRUEH === '1';
31
33
  const smoketestNeuesVerzeichnis = process.env.HMGR_SMOKETEST_NEUES_VERZEICHNIS ?? '';
32
34
  /**
33
35
  * Nur eine hmgr-Instanz je Nutzer (E67). Grund: zwei laufende Fenster schrieben nacheinander auf
@@ -507,6 +509,9 @@ function fensterOeffnen() {
507
509
  sandbox: true,
508
510
  },
509
511
  });
512
+ meldungsPuffer.bereitAbmelden();
513
+ hauptfenster.webContents.on('did-start-loading', () => meldungsPuffer.bereitAbmelden());
514
+ hauptfenster.webContents.on('did-finish-load', () => meldungsPuffer.bereitSetzen());
510
515
  hauptfenster.on('closed', () => {
511
516
  hauptfenster = null;
512
517
  zuletztGemeldeteGuiVersion = null;
@@ -519,7 +524,21 @@ function fensterOeffnen() {
519
524
  console.log(`[renderer] ${event.message}`);
520
525
  });
521
526
  // Nur für den Smoke-Test (scripts/gui-smoke-test.ts): ein DOM-Auszug im Log, danach Ende.
522
- if (smoketest) {
527
+ if (smoketest && smoketestFrueh) {
528
+ // E90-Nachtrag: die Platten-Erkennung feuert schon vor dem Laden der Seite (direkt nach der
529
+ // Fenstererzeugung); die Meldung muss trotzdem ankommen. Kein großer DOM-Auszug, nur das Modal.
530
+ const fenster = hauptfenster;
531
+ plattenVersionPruefen(true);
532
+ fenster.webContents.once('did-finish-load', () => {
533
+ setTimeout(() => {
534
+ void fenster.webContents
535
+ .executeJavaScript(NEUSTART_AUSZUG_SKRIPT)
536
+ .then((auszug) => console.log(`[smoke] Neustart-Modal früh: ${String(auszug)}`))
537
+ .finally(() => app.quit());
538
+ }, 1500);
539
+ });
540
+ }
541
+ if (smoketest && !smoketestFrueh) {
523
542
  const fenster = hauptfenster;
524
543
  fenster.webContents.once('did-finish-load', () => {
525
544
  setTimeout(() => {
@@ -1218,26 +1237,12 @@ function fensterOeffnen() {
1218
1237
  .then(async () => {
1219
1238
  if (process.env.HMGR_GUI_SMOKE_PLATTENVERSION === undefined)
1220
1239
  return;
1240
+ // Der Rest-Dialog (d-erfolg) öffnet über einen 90-ms-Timer nach der letzten Aktion des
1241
+ // Auszugs; ohne dieses Abwarten löste die Erkennung mal vor, mal nach ihm aus.
1242
+ await fenster.webContents.executeJavaScript(`new Promise(function (r) { var n = 0; (function w() { if (document.querySelector('dialog[open]') || ++n > 30) r(); else setTimeout(w, 50); })(); })`);
1221
1243
  plattenVersionPruefen(true);
1222
1244
  await new Promise((r) => setTimeout(r, 800));
1223
- const auszug = await fenster.webContents.executeJavaScript(`(async () => {
1224
- var dlg = document.getElementById('d-neustart');
1225
- // Ein anderer Dialog steht noch offen (Rest des ersten Auszugs): das Modal wartet
1226
- // solange, und öffnet erst, wenn der andere zu ist.
1227
- var anderePlatzhalter = Array.from(document.querySelectorAll('dialog[open]')).filter(function (d) { return d !== dlg; });
1228
- var wartetSolangeAndererOffen = anderePlatzhalter.length > 0 && dlg?.open !== true;
1229
- anderePlatzhalter.forEach(function (d) { d.close(); });
1230
- await new Promise(function (r) { setTimeout(r, 300); });
1231
- var offen = dlg?.open === true;
1232
- var titel = document.getElementById('dn-titel')?.textContent ?? null;
1233
- var zeile = document.getElementById('selbstupdate-gui');
1234
- var zeileText = zeile && !zeile.hidden ? zeile.textContent : null;
1235
- var neustartKnopfSichtbar = document.getElementById('selbstupdate-neustart')?.hidden === false;
1236
- var knopfTexte = Array.from(dlg?.querySelectorAll('.dfuss button') ?? []).map(function (b) { return b.textContent; }).join('|');
1237
- dlg?.querySelector('button[value="spaeter"]')?.click();
1238
- var nachSpaeterOffen = dlg?.open === true;
1239
- return JSON.stringify({ wartetSolangeAndererOffen, offen, titel, zeileText, neustartKnopfSichtbar, knopfTexte, nachSpaeterOffen });
1240
- })()`);
1245
+ const auszug = await fenster.webContents.executeJavaScript(NEUSTART_AUSZUG_SKRIPT);
1241
1246
  console.log(`[smoke] Neustart-Modal: ${String(auszug)}`);
1242
1247
  })
1243
1248
  .finally(() => app.quit());
@@ -1337,11 +1342,40 @@ function updatePruefen() {
1337
1342
  console.log(`[updater] ${fehler instanceof Error ? fehler.message : String(fehler)}`);
1338
1343
  }
1339
1344
  }
1340
- /** Ein Hinweis für die Sidebar (E77). Ist das Fenster schon zu, verfällt er stillschweigend. */
1341
- function selbstUpdateMelden(nachricht) {
1345
+ /** Das Skript für den Modal-Auszug im Smoke-Test (Neustart-Modal, Sidebar-Zeile, „Später"). */
1346
+ const NEUSTART_AUSZUG_SKRIPT = `(async () => {
1347
+ var dlg = document.getElementById('d-neustart');
1348
+ // Ein anderer Dialog steht noch offen (Rest des ersten Auszugs): das Modal wartet
1349
+ // solange, und öffnet erst, wenn der andere zu ist.
1350
+ var anderePlatzhalter = Array.from(document.querySelectorAll('dialog[open]')).filter(function (d) { return d !== dlg; });
1351
+ var wartetSolangeAndererOffen = anderePlatzhalter.length > 0 && dlg?.open !== true;
1352
+ anderePlatzhalter.forEach(function (d) { d.close(); });
1353
+ await new Promise(function (r) { setTimeout(r, 300); });
1354
+ var offen = dlg?.open === true;
1355
+ var titel = document.getElementById('dn-titel')?.textContent ?? null;
1356
+ var zeile = document.getElementById('selbstupdate-gui');
1357
+ var zeileText = zeile && !zeile.hidden ? zeile.textContent : null;
1358
+ var neustartKnopfSichtbar = document.getElementById('selbstupdate-neustart')?.hidden === false;
1359
+ var knopfTexte = Array.from(dlg?.querySelectorAll('.dfuss button') ?? []).map(function (b) { return b.textContent; }).join('|');
1360
+ dlg?.querySelector('button[value="spaeter"]')?.click();
1361
+ var nachSpaeterOffen = dlg?.open === true;
1362
+ return JSON.stringify({ wartetSolangeAndererOffen, offen, titel, zeileText, neustartKnopfSichtbar, knopfTexte, nachSpaeterOffen });
1363
+ })()`;
1364
+ /**
1365
+ * Ein Hinweis für die Sidebar (E77). Ist das Fenster schon zu, verfällt er stillschweigend. Solange
1366
+ * die Seite nicht geladen ist, hat der Renderer seinen Listener noch nicht (E90-Nachtrag): der
1367
+ * Puffer hält je Art die letzte Nachricht und sendet sie nach `did-finish-load` — das Skript am
1368
+ * Ende des Bodys registriert `onSelbstUpdate` synchron, `did-finish-load` kommt erst danach.
1369
+ */
1370
+ const meldungsPuffer = new MeldungsPuffer((nachricht) => {
1342
1371
  if (hauptfenster === null || hauptfenster.isDestroyed())
1343
1372
  return;
1344
1373
  hauptfenster.webContents.send('hmgr:selbstUpdate', nachricht);
1374
+ });
1375
+ function selbstUpdateMelden(nachricht) {
1376
+ if (hauptfenster === null || hauptfenster.isDestroyed())
1377
+ return;
1378
+ meldungsPuffer.melden(nachricht);
1345
1379
  }
1346
1380
  /** Windows: ein Paket ist geladen und wartet auf `quitAndInstall` (E90, Merker für `hmgr:neuStarten`). */
1347
1381
  let geladenesPaketVorhanden = false;
@@ -72,3 +72,34 @@ export function neuereVersionAufPlatte(plistPfad, laufend) {
72
72
  const platte = plistVersion(plistPfad);
73
73
  return platte !== null && istNeuer(platte, laufend) ? platte : null;
74
74
  }
75
+ /**
76
+ * Puffer für Meldungen an den Renderer (E90-Nachtrag). Solange die Seite nicht geladen ist, hat der
77
+ * Renderer seinen Listener noch nicht registriert, ein `webContents.send` ginge ins Leere. Bis
78
+ * `bereitSetzen()` wird deshalb je `art` nur die letzte Nachricht behalten und dann einmal
79
+ * gesendet; danach geht alles sofort durch. `bereitAbmelden()` (neues Laden der Seite) schaltet
80
+ * wieder auf Puffern. Ohne Electron-Import, damit ohne App testbar.
81
+ */
82
+ export class MeldungsPuffer {
83
+ bereit = false;
84
+ wartend = new Map();
85
+ senden;
86
+ constructor(senden) {
87
+ this.senden = senden;
88
+ }
89
+ melden(nachricht) {
90
+ if (this.bereit)
91
+ this.senden(nachricht);
92
+ else
93
+ this.wartend.set(nachricht.art, nachricht);
94
+ }
95
+ bereitSetzen() {
96
+ this.bereit = true;
97
+ const gepuffert = [...this.wartend.values()];
98
+ this.wartend.clear();
99
+ for (const nachricht of gepuffert)
100
+ this.senden(nachricht);
101
+ }
102
+ bereitAbmelden() {
103
+ this.bereit = false;
104
+ }
105
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hmgr",
3
- "version": "0.0.21",
3
+ "version": "0.0.22",
4
4
  "description": "Harness Manager: Skills und Plugins für AI-Harnesses verwalten",
5
5
  "license": "MIT",
6
6
  "author": "Tim Kaufmann",