hmgr 0.0.53 → 0.0.55

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.
@@ -1,6 +1,12 @@
1
1
  {
2
2
  "fassung": 1,
3
3
  "versionen": {
4
+ "0.0.55": [
5
+ "Auch die Dialoge „Verlinken“ und „MCP hinzufügen“ haben jetzt ein Suchfeld. Du kannst über mehrere Suchen hinweg ankreuzen, unten steht, wie viele Einträge ausgewählt sind."
6
+ ],
7
+ "0.0.54": [
8
+ "Der Dialog „Einhängen“ eines MCP-Servers hat jetzt ein Suchfeld. Tippen filtert die Orte nach Name und Pfad, so findest du ein Arbeitsverzeichnis ohne langes Scrollen."
9
+ ],
4
10
  "0.0.53": [
5
11
  "MCP-Server stehen an der Ordnerkarte jetzt in derselben Tabelle wie die Skills, mit dem Zeichen des Harness davor. Ein Tooltip erklärt, warum ein Server für Hermes fehlt: Hermes liest MCP-Server nur im Home oder in einem Profil, nicht pro Ordner. `hmgr mcp list` sagt das am Ende ebenfalls."
6
12
  ],
package/dist/gui/main.js CHANGED
@@ -943,12 +943,64 @@ function fensterOeffnen() {
943
943
  // Verlinken-Dialog „Wohin?" (E76): er bietet nur Ziele aktiver Harnesses an. Der Text
944
944
  // der Wahlliste sagt, welche das sind; ist gar keines aktiv, steht dort der Leerhinweis.
945
945
  var dzZieleText = null;
946
+ // E123: Suchfeld im Verlinken-Dialog (Mehrfachauswahl: Haken bleiben beim Ausblenden).
947
+ var dzSucheVorhanden = false;
948
+ var dzSucheLeerBeimOeffnen = false;
949
+ var dzSucheFokus = false;
950
+ var dzSucheNurTreffer = false;
951
+ var dzSucheAndereVersteckt = false;
952
+ var dzSucheAbgehakt = false;
953
+ var dzSucheBilanz = null;
954
+ var dzSucheLeerhinweis = null;
955
+ var dzSucheLeerhinweisWeg = false;
956
+ var dzSucheEnterOffen = false;
957
+ var dzSucheFehler = null;
946
958
  var dzKnopf = Array.from(document.querySelectorAll('#katalog .zeile button'))
947
959
  .find((b) => b.textContent === 'Verlinken');
948
960
  if (dzKnopf) {
949
961
  dzKnopf.click();
950
962
  dzZieleText = document.getElementById('dz-ziele')?.textContent
951
963
  ?.replace(/\\s+/g, ' ').trim() ?? null;
964
+ try {
965
+ var dzSuche = document.getElementById('dz-suche');
966
+ dzSucheVorhanden = dzSuche !== null;
967
+ dzSucheLeerBeimOeffnen = dzSuche?.value === '';
968
+ dzSucheFokus = document.activeElement?.id === 'dz-suche';
969
+ var dzSetze = (wert) => {
970
+ dzSuche.value = wert;
971
+ dzSuche.dispatchEvent(new Event('input', { bubbles: true }));
972
+ };
973
+ var dzZeilen = () => Array.from(document.querySelectorAll('#dz-ziele .wahlzeile'));
974
+ dzSetze('researcher');
975
+ var dzSichtbar = dzZeilen().filter((z) => !z.hidden);
976
+ dzSucheNurTreffer = dzSichtbar.length > 0
977
+ && dzSichtbar.every((z) => (z.textContent || '').indexOf('researcher') > -1);
978
+ dzSucheAndereVersteckt = dzZeilen().some((z) => z.hidden);
979
+ dzSetze('');
980
+ var dzFrei = dzZeilen().find((z) => z.querySelector('input')?.disabled === false
981
+ && (z.textContent || '').indexOf('researcher') < 0);
982
+ var dzFreiBox = dzFrei?.querySelector('input');
983
+ if (dzFreiBox) {
984
+ dzFreiBox.checked = true;
985
+ dzFreiBox.dispatchEvent(new Event('change', { bubbles: true }));
986
+ dzSetze('researcher');
987
+ dzSucheBilanz = document.getElementById('dz-bilanz')?.textContent ?? null;
988
+ dzSucheAbgehakt = dzFrei.hidden === true && dzFreiBox.checked === true;
989
+ dzSetze('');
990
+ dzFreiBox.checked = false;
991
+ dzFreiBox.dispatchEvent(new Event('change', { bubbles: true }));
992
+ }
993
+ dzSetze('zzzkeintreffer');
994
+ dzSucheLeerhinweis = document.querySelector('#dz-ziele .suchhinweis')?.textContent ?? null;
995
+ dzSetze('');
996
+ dzSucheLeerhinweisWeg = document.querySelector('#dz-ziele .suchhinweis') === null
997
+ && dzZeilen().every((z) => !z.hidden);
998
+ dzSuche.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
999
+ await new Promise((r) => setTimeout(r, 100));
1000
+ dzSucheEnterOffen = document.getElementById('d-ziel')?.open === true;
1001
+ } catch (fehler) {
1002
+ dzSucheFehler = String(fehler);
1003
+ }
952
1004
  document.getElementById('d-ziel')?.close();
953
1005
  }
954
1006
  // Bundle-Gruppe an der Claude-Code-Home-Karte (E69, E114): Kopf mit Name, Quelle, Zählung
@@ -1046,6 +1098,17 @@ function fensterOeffnen() {
1046
1098
  var mcpWahlTextFrei = null;
1047
1099
  // E91: die Wahlzeile des Unterordners im Repo ist deaktiviert und trägt die Notiz.
1048
1100
  var mcpUnterordnerGesperrt = null;
1101
+ var mcpSucheVorhanden = false;
1102
+ var mcpSucheLeerBeimOeffnen = false;
1103
+ var mcpSucheFokus = false;
1104
+ var mcpSucheZeilenGesamt = 0;
1105
+ var mcpSucheNurTreffer = false;
1106
+ var mcpSucheAndereVersteckt = false;
1107
+ var mcpSucheLeerhinweis = null;
1108
+ var mcpSucheLeerhinweisWeg = false;
1109
+ var mcpSucheAbgehakt = false;
1110
+ var mcpSucheEnterOffen = false;
1111
+ var mcpSucheNachNeuOeffnen = false;
1049
1112
  try {
1050
1113
  var mcpEinKnoepfe = Array.from(document.querySelectorAll('#mcpliste .mcpkopf button'))
1051
1114
  .filter((b) => (b.textContent || '').indexOf('Einhängen') === 0);
@@ -1063,6 +1126,44 @@ function fensterOeffnen() {
1063
1126
  mcpUnterordnerGesperrt = Array.from(document.querySelectorAll('#dm-orte .wahlzeile'))
1064
1127
  .filter((z) => (z.textContent || '').indexOf('unterordner') > -1)
1065
1128
  .map((z) => z.querySelector('input')?.disabled === true);
1129
+ // E122: Suchfeld im Dialog. Fokus, Filter, Leerhinweis, Abhaken beim Ausblenden,
1130
+ // Enter ohne Auswahl, Zustand nach erneutem Öffnen.
1131
+ var dmSuche = document.getElementById('dm-suche');
1132
+ mcpSucheVorhanden = dmSuche !== null;
1133
+ mcpSucheLeerBeimOeffnen = dmSuche?.value === '';
1134
+ mcpSucheFokus = document.activeElement?.id === 'dm-suche';
1135
+ var dmSetze = (wert) => {
1136
+ dmSuche.value = wert;
1137
+ dmSuche.dispatchEvent(new Event('input', { bubbles: true }));
1138
+ };
1139
+ var dmZeilen = () => Array.from(document.querySelectorAll('#dm-orte .wahlzeile'));
1140
+ mcpSucheZeilenGesamt = dmZeilen().length;
1141
+ dmSetze('unterordner');
1142
+ var dmSichtbar = dmZeilen().filter((z) => !z.hidden);
1143
+ mcpSucheNurTreffer = dmSichtbar.length > 0
1144
+ && dmSichtbar.every((z) => (z.textContent || '').indexOf('unterordner') > -1);
1145
+ mcpSucheAndereVersteckt = dmZeilen().some((z) => z.hidden);
1146
+ dmSetze('zzzkeintreffer');
1147
+ mcpSucheLeerhinweis = document.querySelector('#dm-orte .leerhinweis')?.textContent ?? null;
1148
+ dmSetze('');
1149
+ mcpSucheLeerhinweisWeg = document.querySelector('#dm-orte .leerhinweis') === null
1150
+ && dmZeilen().every((z) => !z.hidden);
1151
+ var dmFrei = dmZeilen().find((z) => z.querySelector('input')?.disabled === false);
1152
+ var dmFreiRadio = dmFrei?.querySelector('input');
1153
+ if (dmFreiRadio) {
1154
+ dmFreiRadio.checked = true;
1155
+ dmSetze('unterordner');
1156
+ mcpSucheAbgehakt = dmFrei.hidden === true && dmFreiRadio.checked === false;
1157
+ }
1158
+ dmSetze('');
1159
+ dmSuche.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
1160
+ await new Promise((r) => setTimeout(r, 100));
1161
+ mcpSucheEnterOffen = document.getElementById('d-mcp')?.open === true;
1162
+ dmSetze('unterordner');
1163
+ document.querySelector('#d-mcp button[value="abbruch"]')?.click();
1164
+ await mcpWahlOeffnen(mcpEinKnoepfe[1]);
1165
+ mcpSucheNachNeuOeffnen = document.getElementById('dm-suche')?.value === ''
1166
+ && dmZeilen().length > 0 && dmZeilen().every((z) => !z.hidden);
1066
1167
  document.querySelector('#d-mcp button[value="abbruch"]')?.click();
1067
1168
  } catch (fehler) {
1068
1169
  mcpFehler = String(fehler);
@@ -1182,10 +1283,58 @@ function fensterOeffnen() {
1182
1283
  var dMcpHinzuOffenNachOeffnen = false;
1183
1284
  var dMcpHinzuOffenNachAbbrechen = true;
1184
1285
  var dmhListeText = null;
1286
+ // E123: Suchfeld im Dialog „MCP hinzufügen".
1287
+ var dmhSucheVorhanden = false;
1288
+ var dmhSucheBlockHidden = null;
1289
+ var dmhSucheLeerBeimOeffnen = false;
1290
+ var dmhSucheFokus = false;
1291
+ var dmhSucheNurTreffer = false;
1292
+ var dmhSucheAndereVersteckt = false;
1293
+ var dmhSucheAbgehakt = false;
1294
+ var dmhSucheBilanz = null;
1295
+ var dmhSucheLeerhinweis = null;
1296
+ var dmhSucheEnterOffen = false;
1185
1297
  try {
1186
1298
  mcpHinzuKnopfAn(hermesKarte)?.click();
1187
1299
  dMcpHinzuOffenNachOeffnen = document.getElementById('d-mcp-hinzufuegen')?.open === true;
1188
1300
  dmhListeText = document.getElementById('dmh-liste')?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
1301
+ var dmhSuche = document.getElementById('dmh-suche');
1302
+ dmhSucheVorhanden = dmhSuche !== null;
1303
+ dmhSucheBlockHidden = document.getElementById('dmh-suchblock')?.hidden ?? null;
1304
+ dmhSucheLeerBeimOeffnen = dmhSuche?.value === '';
1305
+ dmhSucheFokus = document.activeElement?.id === 'dmh-suche';
1306
+ var dmhSetze = (wert) => {
1307
+ dmhSuche.value = wert;
1308
+ dmhSuche.dispatchEvent(new Event('input', { bubbles: true }));
1309
+ };
1310
+ var dmhZeilen = () => Array.from(document.querySelectorAll('#dmh-liste .wahlzeile'));
1311
+ if (dmhZeilen().length > 0) {
1312
+ dmhSetze('mail');
1313
+ var dmhSichtbar = dmhZeilen().filter((z) => !z.hidden);
1314
+ dmhSucheNurTreffer = dmhSichtbar.length > 0
1315
+ && dmhSichtbar.every((z) => (z.textContent || '').indexOf('mail') > -1);
1316
+ dmhSucheAndereVersteckt = dmhZeilen().some((z) => z.hidden);
1317
+ dmhSetze('');
1318
+ var dmhFrei = dmhZeilen().find((z) => z.querySelector('input')?.disabled === false
1319
+ && (z.textContent || '').indexOf('mail') < 0);
1320
+ var dmhFreiBox = dmhFrei?.querySelector('input');
1321
+ if (dmhFreiBox) {
1322
+ dmhFreiBox.checked = true;
1323
+ dmhFreiBox.dispatchEvent(new Event('change', { bubbles: true }));
1324
+ dmhSetze('mail');
1325
+ dmhSucheBilanz = document.getElementById('dmh-bilanz')?.textContent ?? null;
1326
+ dmhSucheAbgehakt = dmhFrei.hidden === true && dmhFreiBox.checked === true;
1327
+ dmhSetze('');
1328
+ dmhFreiBox.checked = false;
1329
+ dmhFreiBox.dispatchEvent(new Event('change', { bubbles: true }));
1330
+ }
1331
+ dmhSetze('zzzkeintreffer');
1332
+ dmhSucheLeerhinweis = document.querySelector('#dmh-liste .suchhinweis')?.textContent ?? null;
1333
+ dmhSetze('');
1334
+ dmhSuche.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter', bubbles: true }));
1335
+ await new Promise((r) => setTimeout(r, 100));
1336
+ dmhSucheEnterOffen = document.getElementById('d-mcp-hinzufuegen')?.open === true;
1337
+ }
1189
1338
  document.querySelector('#d-mcp-hinzufuegen button[value="abbruch"]')?.click();
1190
1339
  dMcpHinzuOffenNachAbbrechen = document.getElementById('d-mcp-hinzufuegen')?.open === true;
1191
1340
  } catch (fehler) {
@@ -1313,6 +1462,17 @@ function fensterOeffnen() {
1313
1462
  dskBundleZuVorher,
1314
1463
  dskBundleKoerperText,
1315
1464
  dzZieleText,
1465
+ dzSucheVorhanden,
1466
+ dzSucheLeerBeimOeffnen,
1467
+ dzSucheFokus,
1468
+ dzSucheNurTreffer,
1469
+ dzSucheAndereVersteckt,
1470
+ dzSucheAbgehakt,
1471
+ dzSucheBilanz,
1472
+ dzSucheLeerhinweis,
1473
+ dzSucheLeerhinweisWeg,
1474
+ dzSucheEnterOffen,
1475
+ dzSucheFehler,
1316
1476
  bundleGruppeText,
1317
1477
  bundleGruppeZeilen,
1318
1478
  bundleNichtVerlinktText,
@@ -1367,6 +1527,17 @@ function fensterOeffnen() {
1367
1527
  mcpWahlText,
1368
1528
  mcpWahlTextFrei,
1369
1529
  mcpUnterordnerGesperrt,
1530
+ mcpSucheVorhanden,
1531
+ mcpSucheLeerBeimOeffnen,
1532
+ mcpSucheFokus,
1533
+ mcpSucheZeilenGesamt,
1534
+ mcpSucheNurTreffer,
1535
+ mcpSucheAndereVersteckt,
1536
+ mcpSucheLeerhinweis,
1537
+ mcpSucheLeerhinweisWeg,
1538
+ mcpSucheAbgehakt,
1539
+ mcpSucheEnterOffen,
1540
+ mcpSucheNachNeuOeffnen,
1370
1541
  mcpFehler,
1371
1542
  dMcpAusOffenNachOeffnen,
1372
1543
  dMcpAusOffenNachAbbrechen,
@@ -1400,6 +1571,16 @@ function fensterOeffnen() {
1400
1571
  dMcpHinzuOffenNachOeffnen,
1401
1572
  dMcpHinzuOffenNachAbbrechen,
1402
1573
  dmhListeText,
1574
+ dmhSucheVorhanden,
1575
+ dmhSucheBlockHidden,
1576
+ dmhSucheLeerBeimOeffnen,
1577
+ dmhSucheFokus,
1578
+ dmhSucheNurTreffer,
1579
+ dmhSucheAndereVersteckt,
1580
+ dmhSucheAbgehakt,
1581
+ dmhSucheBilanz,
1582
+ dmhSucheLeerhinweis,
1583
+ dmhSucheEnterOffen,
1403
1584
  dmhFehler,
1404
1585
  selbstupdateVorhanden,
1405
1586
  selbstupdateVerborgen,
@@ -214,8 +214,15 @@
214
214
  <h3>Wohin soll <span id="dz-skill">der Skill</span>?</h3>
215
215
  <p>Kreuz jedes Ziel an, in dem der Skill auftauchen soll.</p>
216
216
  </div>
217
- <div class="dkoerper"><div class="wahl" id="dz-ziele"></div></div>
217
+ <div class="dkoerper">
218
+ <div class="suche">
219
+ <svg viewBox="0 0 16 16" stroke-width="1.6" aria-hidden="true"><circle cx="7" cy="7" r="4.5"/><path d="M10.5 10.5 14.5 14.5"/></svg>
220
+ <input type="search" id="dz-suche" placeholder="Ziel oder Pfad suchen" aria-label="Ziele durchsuchen" spellcheck="false" autocomplete="off">
221
+ </div>
222
+ <div class="wahl" id="dz-ziele"></div>
223
+ </div>
218
224
  <div class="dfuss">
225
+ <span class="links mono" id="dz-bilanz">0 ausgewählt</span>
219
226
  <button class="knopf leise" value="abbruch">Abbrechen</button>
220
227
  <button class="knopf signal" value="los" id="dz-los">Verlinken</button>
221
228
  </div>
@@ -573,7 +580,13 @@
573
580
  <h3>Wohin soll <span id="dm-name">der Server</span>?</h3>
574
581
  <p id="dm-text">Ein Ort je Einhängen. agents kennt keine MCP-Server und steht deshalb nicht zur Wahl.</p>
575
582
  </div>
576
- <div class="dkoerper"><div class="wahl" id="dm-orte"></div></div>
583
+ <div class="dkoerper">
584
+ <div class="suche">
585
+ <svg viewBox="0 0 16 16" stroke-width="1.6" aria-hidden="true"><circle cx="7" cy="7" r="4.5"/><path d="M10.5 10.5 14.5 14.5"/></svg>
586
+ <input type="search" id="dm-suche" placeholder="Ort oder Pfad suchen" aria-label="Orte durchsuchen" spellcheck="false" autocomplete="off">
587
+ </div>
588
+ <div class="wahl" id="dm-orte"></div>
589
+ </div>
577
590
  <div class="dfuss">
578
591
  <button class="knopf leise" value="abbruch">Abbrechen</button>
579
592
  <button class="knopf signal" value="los" id="dm-los">Einhängen</button>
@@ -589,6 +602,10 @@
589
602
  <p>Kreuz jeden Server an, der hier eingehängt werden soll. Schon Eingehängtes ist ausgegraut.</p>
590
603
  </div>
591
604
  <div class="dkoerper">
605
+ <div class="suche" id="dmh-suchblock">
606
+ <svg viewBox="0 0 16 16" stroke-width="1.6" aria-hidden="true"><circle cx="7" cy="7" r="4.5"/><path d="M10.5 10.5 14.5 14.5"/></svg>
607
+ <input type="search" id="dmh-suche" placeholder="Server suchen" aria-label="Server durchsuchen" spellcheck="false" autocomplete="off">
608
+ </div>
592
609
  <div class="wahl" id="dmh-liste"></div>
593
610
  </div>
594
611
  <div class="dfuss">
@@ -2447,6 +2447,7 @@
2447
2447
  $('dz-skill').textContent = skill.name;
2448
2448
  var box = $('dz-ziele');
2449
2449
  box.textContent = '';
2450
+ $('dz-suche').value = '';
2450
2451
  // E76: Ziele inaktiver Harnesses stehen gar nicht erst zur Wahl — der Kern lehnte den Link
2451
2452
  // ohnehin ab, und seit E74 zeigt keine Ansicht sie. Dieselbe Regel wie die Zielliste.
2452
2453
  var waehlbar = ZIELE.filter(zielSichtbar);
@@ -2460,10 +2461,12 @@
2460
2461
  return n === skill.name;
2461
2462
  });
2462
2463
  var label = e('label', 'wahlzeile');
2464
+ label.dataset.index = String(ZIELE.indexOf(z));
2463
2465
  var input = document.createElement('input');
2464
2466
  input.type = 'checkbox';
2465
2467
  input.value = String(ZIELE.indexOf(z));
2466
2468
  input.disabled = schon;
2469
+ input.addEventListener('change', dzBilanzAktualisieren);
2467
2470
  label.appendChild(input);
2468
2471
  var txt = e('span');
2469
2472
  txt.appendChild(beschriftet(e('b', null, zielTitel(z)), z.ziel.harness));
@@ -2472,9 +2475,42 @@
2472
2475
  label.appendChild(txt);
2473
2476
  box.appendChild(label);
2474
2477
  });
2478
+ dzBilanzAktualisieren();
2475
2479
  zeige($('d-ziel'));
2480
+ $('dz-suche').focus();
2476
2481
  }
2477
2482
 
2483
+ function dzBilanzAktualisieren() {
2484
+ var n = $('dz-ziele').querySelectorAll('input:checked').length;
2485
+ $('dz-bilanz').textContent = zahlwort(n, 'ausgewählt', 'ausgewählt');
2486
+ }
2487
+
2488
+ /** E123: filtert die Wahlzeilen des Verlinken-Dialogs live. Mehrfachauswahl: angehakte Zeilen
2489
+ bleiben auch ausgeblendet angehakt, damit man über mehrere Suchen hinweg sammeln kann. */
2490
+ function filtereDzZiele() {
2491
+ var begriff = $('dz-suche').value.trim();
2492
+ var suche = suchform(begriff);
2493
+ var box = $('dz-ziele');
2494
+ var gezeigt = 0;
2495
+ box.querySelectorAll('.wahlzeile').forEach(function (label) {
2496
+ var z = ZIELE[+label.dataset.index];
2497
+ var passt = true;
2498
+ if (suche) {
2499
+ var text = suchform(zielTitel(z) + ' ' + z.verzeichnis + ' ' + pfadKurz(z.verzeichnis));
2500
+ passt = text.indexOf(suche) > -1;
2501
+ }
2502
+ label.hidden = !passt;
2503
+ if (passt) gezeigt++;
2504
+ });
2505
+ var alt = box.querySelector('.suchhinweis');
2506
+ if (alt) alt.remove();
2507
+ if (suche && gezeigt === 0) {
2508
+ box.appendChild(e('p', 'leerhinweis suchhinweis', 'Kein Ziel passt zu „' + begriff + '".'));
2509
+ }
2510
+ }
2511
+ $('dz-suche').addEventListener('input', filtereDzZiele);
2512
+ enterBestaetigt($('dz-suche'), $('dz-los'));
2513
+
2478
2514
  $('d-ziel').addEventListener('submit', function (ev) {
2479
2515
  if (ev.submitter && ev.submitter.value === 'los') {
2480
2516
  var gewaehlt = Array.from($('dz-ziele').querySelectorAll('input:checked'));
@@ -3697,6 +3733,7 @@
3697
3733
  $('dm-text').textContent = 'Ein Ort je Einhängen. agents kennt keine MCP-Server und steht deshalb nicht zur Wahl.';
3698
3734
  var box = $('dm-orte');
3699
3735
  box.textContent = '';
3736
+ $('dm-suche').value = '';
3700
3737
  // Die Plätze kommen aus dem Kern (F42, E16): die Fähigkeit hängt am Adapter, nicht am
3701
3738
  // Harness-Namen, hier wird nicht selbst entschieden, wer welche Ebene kennt.
3702
3739
  var plaetze = await rufe(function () { return window.hmgr.mcpPlaetze(); });
@@ -3711,6 +3748,7 @@
3711
3748
  var schon = k.eingehaengt.some(function (z) { return zielKey(z) === zielKey(ziel); });
3712
3749
  var aktiv = harnessAktiv(ziel.harness);
3713
3750
  var label = e('label', 'wahlzeile');
3751
+ label.dataset.index = i;
3714
3752
  var input = document.createElement('input');
3715
3753
  input.type = 'radio';
3716
3754
  input.name = 'mcport';
@@ -3742,7 +3780,41 @@
3742
3780
  box.appendChild(label);
3743
3781
  });
3744
3782
  zeige($('d-mcp'));
3783
+ $('dm-suche').focus();
3784
+ }
3785
+
3786
+ /** E122: filtert die Wahlzeilen des Einhängen-Dialogs live. Die Zeilen bleiben stehen (der
3787
+ Radio-Wert ist der Index in mcpPlaetzeAuswahl), nicht passende werden nur ausgeblendet. Eine
3788
+ angehakte Zeile, die verschwindet, wird abgehakt: sonst ginge „Einhängen" an einen Ort, den
3789
+ niemand mehr sieht. */
3790
+ function filtereMcpOrte() {
3791
+ var begriff = $('dm-suche').value.trim();
3792
+ var suche = suchform(begriff);
3793
+ var box = $('dm-orte');
3794
+ var gezeigt = 0;
3795
+ box.querySelectorAll('.wahlzeile').forEach(function (label) {
3796
+ var ziel = mcpPlaetzeAuswahl[+label.dataset.index];
3797
+ var passt = true;
3798
+ if (suche) {
3799
+ var pfad = ziel.ort.art === 'arbeitsverzeichnis' ? ziel.ort.pfad : '';
3800
+ var text = suchform(zielTitel({ ziel: ziel }) + ' ' + mcpOrtSpur(ziel) + ' ' + pfad + ' ' + pfadKurz(pfad));
3801
+ passt = text.indexOf(suche) > -1;
3802
+ }
3803
+ label.hidden = !passt;
3804
+ if (passt) gezeigt++;
3805
+ else {
3806
+ var radio = label.querySelector('input');
3807
+ if (radio) radio.checked = false;
3808
+ }
3809
+ });
3810
+ var alt = box.querySelector('.leerhinweis');
3811
+ if (alt) alt.remove();
3812
+ if (suche && gezeigt === 0) {
3813
+ box.appendChild(e('p', 'leerhinweis', 'Kein Ort passt zu „' + begriff + '".'));
3814
+ }
3745
3815
  }
3816
+ $('dm-suche').addEventListener('input', filtereMcpOrte);
3817
+ enterBestaetigt($('dm-suche'), $('dm-los'));
3746
3818
 
3747
3819
  $('d-mcp').addEventListener('submit', function (ev) {
3748
3820
  if (ev.submitter && ev.submitter.value === 'los') {
@@ -3834,6 +3906,8 @@
3834
3906
  $('dmh-ziel').textContent = zielTitel({ ziel: ziel });
3835
3907
  var box = $('dmh-liste');
3836
3908
  box.textContent = '';
3909
+ $('dmh-suche').value = '';
3910
+ $('dmh-suchblock').hidden = MCP_KATALOG.length === 0;
3837
3911
  // Ohne Katalog stünde hier ein leerer Kasten mit einem Knopf, der nichts tut: hmgr legt
3838
3912
  // MCP-Einträge nie selbst an (E61), also nennt der Dialog denselben Weg wie die MCP-Ansicht.
3839
3913
  if (MCP_KATALOG.length === 0) {
@@ -3849,6 +3923,7 @@
3849
3923
  var i = p.i;
3850
3924
  var schon = k.eingehaengt.some(function (z) { return zielKey(z) === zielKey(ziel); });
3851
3925
  var label = e('label', 'wahlzeile');
3926
+ label.dataset.index = String(i);
3852
3927
  var input = document.createElement('input');
3853
3928
  input.type = 'checkbox';
3854
3929
  input.value = String(i);
@@ -3864,7 +3939,33 @@
3864
3939
  });
3865
3940
  dmhBilanzAktualisieren();
3866
3941
  zeige($('d-mcp-hinzufuegen'));
3942
+ if (!$('dmh-suchblock').hidden) $('dmh-suche').focus();
3943
+ }
3944
+
3945
+ /** E123: filtert die Server im Dialog „MCP hinzufügen" nach Name und Beschreibung. Angehakte
3946
+ Zeilen bleiben auch ausgeblendet angehakt (Mehrfachauswahl). */
3947
+ function filtereDmhListe() {
3948
+ var begriff = $('dmh-suche').value.trim();
3949
+ var suche = suchform(begriff);
3950
+ var box = $('dmh-liste');
3951
+ var gezeigt = 0;
3952
+ box.querySelectorAll('.wahlzeile').forEach(function (label) {
3953
+ var k = MCP_KATALOG[+label.dataset.index];
3954
+ var passt = true;
3955
+ if (suche) {
3956
+ passt = suchform(k.eintrag.name + ' ' + (k.eintrag.beschreibung || '')).indexOf(suche) > -1;
3957
+ }
3958
+ label.hidden = !passt;
3959
+ if (passt) gezeigt++;
3960
+ });
3961
+ var alt = box.querySelector('.suchhinweis');
3962
+ if (alt) alt.remove();
3963
+ if (suche && gezeigt === 0) {
3964
+ box.appendChild(e('p', 'leerhinweis suchhinweis', 'Kein Server passt zu „' + begriff + '".'));
3965
+ }
3867
3966
  }
3967
+ $('dmh-suche').addEventListener('input', filtereDmhListe);
3968
+ enterBestaetigt($('dmh-suche'), $('dmh-los'));
3868
3969
 
3869
3970
  $('d-mcp-hinzufuegen').addEventListener('submit', function (ev) {
3870
3971
  if (ev.submitter && ev.submitter.value === 'los') {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hmgr",
3
- "version": "0.0.53",
3
+ "version": "0.0.55",
4
4
  "description": "Harness Manager: Skills und Plugins für AI-Harnesses verwalten",
5
5
  "license": "MIT",
6
6
  "author": "Tim Kaufmann",