hmgr 0.0.5 → 0.0.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.
@@ -9,7 +9,7 @@ import { urlOrt } from "../kern/quelle-ort.js";
9
9
  * (`git@host:besitzer/repo.git`) hat keine Webseite als Adresse, aber Host, Besitzer und Repo sind
10
10
  * bekannt (E36), also wird daraus die https-Repo-Seite gebaut — `shell.openExternal` bekommt so nie
11
11
  * die ssh-Adresse selbst zu sehen. Lokale Quellen und `file://`-Quellen öffnen ihren Pfad im
12
- * Finder. Alles, woraus sich weder eine http(s)-Adresse noch ein Pfad gewinnen lässt, wird
12
+ * Dateimanager. Alles, woraus sich weder eine http(s)-Adresse noch ein Pfad gewinnen lässt, wird
13
13
  * abgelehnt: kein anderes Protokoll geht an eine Electron-Shell-Funktion.
14
14
  */
15
15
  export function entscheideOeffnen(quelle) {
@@ -5,13 +5,15 @@ contextBridge.exposeInMainWorld('hmgr', {
5
5
  version: () => ipcRenderer.invoke('hmgr:version'),
6
6
  /** Home-Verzeichnis, nur für pfadKurz im Renderer (Anzeige-Kürzung auf ~). */
7
7
  home: () => ipcRenderer.invoke('hmgr:home'),
8
+ /** Plattform (`process.platform`), nur für den Pfadtrenner der Anzeige im Renderer (E68). */
9
+ plattform: () => ipcRenderer.invoke('hmgr:plattform'),
8
10
  istZustand: () => ipcRenderer.invoke('hmgr:istZustand'),
9
11
  marketplaces: () => ipcRenderer.invoke('hmgr:marketplaces'),
10
12
  skills: () => ipcRenderer.invoke('hmgr:skills'),
11
13
  quellen: () => ipcRenderer.invoke('hmgr:quellen'),
12
14
  /** Icon einer Quelle als data-URL, oder null (E60). */
13
15
  icon: (text) => ipcRenderer.invoke('hmgr:icon', text),
14
- /** Öffnet eine Quelle: Repo-Seite im Browser oder Ordner im Finder (E60). */
16
+ /** Öffnet eine Quelle: Repo-Seite im Browser oder Ordner im Dateimanager (E60). */
15
17
  quelleOeffnen: (text) => ipcRenderer.invoke('hmgr:quelleOeffnen', text),
16
18
  quelleHinzufuegen: (text, name) => ipcRenderer.invoke('hmgr:quelleHinzufuegen', text, name),
17
19
  quelleEntfernen: (text) => ipcRenderer.invoke('hmgr:quelleEntfernen', text),
@@ -52,4 +54,17 @@ contextBridge.exposeInMainWorld('hmgr', {
52
54
  onAktualisierenAnstossen: (hoerer) => {
53
55
  ipcRenderer.on('hmgr:aktualisierenAnstossen', () => hoerer());
54
56
  },
57
+ /** Anstoß zum stillen Neuladen der Anzeige (E62): Main ruft bei Fokus-Wechsel und beobachteten
58
+ Dateiänderungen, nie mit Netzzugriff (im Unterschied zu onAktualisierenAnstossen). */
59
+ onNeuLadenAnstossen: (hoerer) => {
60
+ ipcRenderer.on('hmgr:neuLadenAnstossen', () => hoerer());
61
+ },
62
+ /** MCP-Ansicht (E61-Folgerunde): Katalog gelesen, nie geschrieben. */
63
+ mcpUebersicht: () => ipcRenderer.invoke('hmgr:mcpUebersicht'),
64
+ /** Plätze für den Einhängen-Dialog (F42): kommt aus dem Kern, hängt an der Fähigkeit (E16). */
65
+ mcpPlaetze: () => ipcRenderer.invoke('hmgr:mcpPlaetze'),
66
+ mcpEinhaengen: (args) => ipcRenderer.invoke('hmgr:mcpEinhaengen', args),
67
+ mcpAushaengen: (args) => ipcRenderer.invoke('hmgr:mcpAushaengen', args),
68
+ /** Übernehmen aus der geteilten .mcp.json in den privaten Scope (E64), nach Bestätigung im Renderer. */
69
+ mcpUebernehmen: (args) => ipcRenderer.invoke('hmgr:mcpUebernehmen', args),
55
70
  });
@@ -3,7 +3,7 @@
3
3
  <head>
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>hmgr — Skills und Plugins auf diesem Rechner</title>
6
+ <title>hmgr — The Harness Manager</title>
7
7
  <!-- Nichts aus dem Netz: der Entwurf holt Inter und JetBrains Mono von Google, eine Desktop-App
8
8
  lädt keine fremden Ressourcen. Beide Schriften liegen deshalb als woff2 unter renderer/fonts/
9
9
  und werden in styles.css per @font-face eingebunden, 'self' deckt sie ab. -->
@@ -25,14 +25,20 @@
25
25
  <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M1 5h14M1 11h14"/><path d="M4 3v4M9 3v4M6 9v4M12 9v4"/></svg>
26
26
  Ziele <span class="zahl" id="navzahlziele"></span>
27
27
  </button>
28
- <button class="plakette" data-ansicht="katalog">
29
- <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M2 3h12v10H2z"/><path d="M2 6h12M6 6v7"/></svg>
30
- Skills <span class="zahl" id="navzahlskills"></span>
28
+ <!-- Stecker mit zwei Stiften: der MCP-Katalog haengt Server in Harnesses ein, mehr sagt das
29
+ Zeichen nicht (entwurf/gui.html, keine Marken-Logos wie bei den Harnessen). -->
30
+ <button class="plakette" data-ansicht="mcp">
31
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M1.4 8h3.2"/><path d="M4.6 3.9h4v8.2h-4z"/><path d="M8.6 6.2h5.8M8.6 9.8h5.8"/></svg>
32
+ MCP <span class="zahl" id="navzahlmcp"></span>
31
33
  </button>
32
34
  <button class="plakette" data-ansicht="plugins">
33
35
  <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M3 3h10v10H3z"/><path d="M6 1v2M10 1v2M6 13v2M10 13v2"/></svg>
34
36
  Plugins <span class="zahl" id="navzahlplugins"></span>
35
37
  </button>
38
+ <button class="plakette" data-ansicht="katalog">
39
+ <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M2 3h12v10H2z"/><path d="M2 6h12M6 6v7"/></svg>
40
+ Skills <span class="zahl" id="navzahlskills"></span>
41
+ </button>
36
42
  </nav>
37
43
 
38
44
  <div class="stand">
@@ -93,14 +99,35 @@
93
99
  <button class="chip" data-zielfilter="alle" aria-pressed="true">Alle</button>
94
100
  <button class="chip" data-zielfilter="achtung" aria-pressed="false">Benötigt Aufmerksamkeit (0)</button>
95
101
  </div>
102
+ </div>
103
+
104
+ <p class="katalogzahl" id="zielzahl"></p>
105
+ <div class="ziele" id="zielliste"></div>
106
+ <!-- Unter der letzten Verzeichnis-Karte, nicht oben bei den Agents: dort gehört er
107
+ thematisch hin (2026-09-05). Fester Fuß statt Teil der neu gebauten Liste, so bleibt
108
+ der Klick-Listener aus der Startphase gebunden. -->
109
+ <div class="zielfussleiste">
96
110
  <button class="knopf leise mitsymbol" type="button" id="verzneu">
97
111
  <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" aria-hidden="true"><path d="M1.2 13.2V4.1h3.9l1.3 1.8h5.2v7.3z"/><path d="M13.2 1.9v4.6M10.9 4.2h4.6"/></svg>
98
112
  Verzeichnis hinzufügen
99
113
  </button>
100
114
  </div>
115
+ </section>
101
116
 
102
- <p class="katalogzahl" id="zielzahl"></p>
103
- <div class="ziele" id="zielliste"></div>
117
+ <!-- ============ MCP ============ -->
118
+ <!-- E61, abgespeckt zum reinen Katalog (F46, Korrektur an E61): der Katalog wird hier nicht
119
+ bearbeitet, hmgr liest ~/.hmgr/mcp.yaml und schreibt sie nie, also gibt es in dieser
120
+ Ansicht kein Anlegen und kein Ändern eines Eintrags, nur Einhängen. Wo ein Server hängt
121
+ und das Aushängen zeigen seither nur noch die Ziel-Karten. -->
122
+ <section id="ansicht-mcp" hidden>
123
+ <div class="ansichtskopf">
124
+ <h1>MCP-Server</h1>
125
+ <!-- Der Pfad steht hier in POSIX-Schreibweise und wird beim Start in die Schreibweise
126
+ der Plattform gesetzt (E68, ladeUmgebung im Renderer). -->
127
+ <p>Dein Katalog aus <span class="mono" id="mcpkatalogpfad">~/.hmgr/mcp.yaml</span>. Häng einen Server dorthin ein, wo du ihn brauchst: in ein Arbeitsverzeichnis, damit er nur dort Kontext kostet, oder global. Den Katalog selbst pflegst du in der Datei, hmgr liest sie nur.</p>
128
+ </div>
129
+
130
+ <div class="mcpliste" id="mcpliste"></div>
104
131
  </section>
105
132
 
106
133
  <!-- ============ AKTUALISIEREN ============ -->
@@ -457,6 +484,69 @@
457
484
  </form>
458
485
  </dialog>
459
486
 
487
+ <dialog id="d-mcp">
488
+ <form method="dialog">
489
+ <div class="dkopf">
490
+ <span class="etikett">Einhängen</span>
491
+ <h3>Wohin soll <span id="dm-name">der Server</span>?</h3>
492
+ <p id="dm-text">Ein Ort je Einhängen. agents kennt keine MCP-Server und steht deshalb nicht zur Wahl.</p>
493
+ </div>
494
+ <div class="dkoerper"><div class="wahl" id="dm-orte"></div></div>
495
+ <div class="dfuss">
496
+ <button class="knopf leise" value="abbruch">Abbrechen</button>
497
+ <button class="knopf signal" value="los" id="dm-los">Einhängen</button>
498
+ </div>
499
+ </form>
500
+ </dialog>
501
+
502
+ <dialog id="d-mcp-hinzufuegen">
503
+ <form method="dialog">
504
+ <div class="dkopf">
505
+ <span class="etikett">MCP hinzufügen</span>
506
+ <h3>Welche MCP-Server sollen in <span id="dmh-ziel">diesem Ziel</span> hängen?</h3>
507
+ <p>Kreuz jeden Server an, der hier eingehängt werden soll. Schon Eingehängtes ist ausgegraut.</p>
508
+ </div>
509
+ <div class="dkoerper">
510
+ <div class="wahl" id="dmh-liste"></div>
511
+ </div>
512
+ <div class="dfuss">
513
+ <span class="links mono" id="dmh-bilanz">0 ausgewählt</span>
514
+ <button class="knopf leise" value="abbruch">Abbrechen</button>
515
+ <button class="knopf signal" value="los" id="dmh-los">Einhängen</button>
516
+ </div>
517
+ </form>
518
+ </dialog>
519
+
520
+ <dialog id="d-mcpaus">
521
+ <form method="dialog">
522
+ <div class="dkopf">
523
+ <span class="etikett">Rückfrage</span>
524
+ <h3 id="dma-titel">Aushängen?</h3>
525
+ <p id="dma-text"></p>
526
+ </div>
527
+ <div class="dfuss">
528
+ <button class="knopf leise" value="nein">Nein, behalten</button>
529
+ <button class="knopf signal" value="ja">Ja, aushängen</button>
530
+ </div>
531
+ </form>
532
+ </dialog>
533
+
534
+ <!-- Uebernehmen aus der geteilten .mcp.json (E64): die einzige Aktion, mit der hmgr diese Datei
535
+ schreibt, deshalb eine eigene Rueckfrage vor dem Ausfuehren. -->
536
+ <dialog id="d-mcpueb">
537
+ <form method="dialog">
538
+ <div class="dkopf">
539
+ <span class="etikett">Rückfrage</span>
540
+ <h3 id="dmu-titel">Übernehmen?</h3>
541
+ <p id="dmu-text"></p>
542
+ </div>
543
+ <div class="dfuss">
544
+ <button class="knopf leise" value="nein">Nein, so lassen</button>
545
+ <button class="knopf signal" value="ja">Ja, übernehmen</button>
546
+ </div>
547
+ </form>
548
+ </dialog>
549
+
460
550
  <dialog id="d-einstellungen">
461
551
  <form method="dialog">
462
552
  <div class="dkopf">