hmgr 0.0.44 → 0.0.46
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/adapter/zustand-json.js +2 -1
- package/dist/aenderungen.json +6 -0
- package/dist/cli/hilfe.js +10 -3
- package/dist/cli/main.js +35 -10
- package/dist/gui/main.js +83 -15
- package/dist/gui/preload.cjs +2 -0
- package/dist/gui/renderer/renderer.js +338 -92
- package/dist/gui/renderer/styles.css +8 -0
- package/dist/kern/anwendungsfaelle.js +131 -45
- package/package.json +1 -1
|
@@ -18,7 +18,8 @@ function deuten(roh) {
|
|
|
18
18
|
aktiveHarnesses: (daten.aktiveHarnesses ?? ['claude-code']),
|
|
19
19
|
// Fehlt das Feld (state.json vor E43), gilt: nichts ignoriert.
|
|
20
20
|
ignorierteEintraege: (daten.ignorierteEintraege ?? []),
|
|
21
|
-
// Fehlt das Feld (state.json vor E69), gilt: kein Bundle installiert.
|
|
21
|
+
// Fehlt das Feld (state.json vor E69), gilt: kein Bundle installiert. Ein Eintrag ohne
|
|
22
|
+
// `herausgenommen` (vor E114) hat keine herausgenommenen Mitglieder, das Feld bleibt dann weg.
|
|
22
23
|
bundleInstallationen: (daten.bundleInstallationen ?? []),
|
|
23
24
|
// Fehlt das Feld (state.json vor E78), gilt: jeder Harness hat nur sein Standard-Homedir.
|
|
24
25
|
harnessHeime: (daten.harnessHeime ?? []),
|
package/dist/aenderungen.json
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"fassung": 1,
|
|
3
3
|
"versionen": {
|
|
4
|
+
"0.0.46": [
|
|
5
|
+
"Bundles lassen sich aufklappen und zeigen ihre Skills mit Beschreibung, auch schon im Dialog „Skills hinzufügen“. Entfernst du einen einzelnen Skill, bleibt das Bundle bestehen und zeigt, was fehlt; mit „Vervollständigen“ oder „Wieder verlinken“ holst du Skills zurück, und „Entfernen“ am Bundle räumt den Rest weg."
|
|
6
|
+
],
|
|
7
|
+
"0.0.45": [
|
|
8
|
+
"MCP-Server und die Listen in den Einstellungen (Harnesses, zusätzliche Homedirs) erscheinen jetzt alphabetisch sortiert, ebenso in hmgr mcp list."
|
|
9
|
+
],
|
|
4
10
|
"0.0.44": [
|
|
5
11
|
"Läuft gerade eine Aktualisierung, zeigt hmgr ein im Terminal hinzugefügtes Verzeichnis trotzdem sofort an, statt bis zum Ende der Aktualisierung zu warten."
|
|
6
12
|
],
|
package/dist/cli/hilfe.js
CHANGED
|
@@ -315,9 +315,13 @@ Liegt am Ziel schon derselbe Skill aus derselben Quelle als hmgr-Link, wird er a
|
|
|
315
315
|
übernommen: aus Bestand wird ein Bundle, ohne erst Links von Hand zu entfernen. Alles andere unter
|
|
316
316
|
demselben Namen ist ein Konflikt und wird genannt.
|
|
317
317
|
|
|
318
|
-
hmgr unlink <skill> auf ein einzelnes Mitglied
|
|
319
|
-
|
|
320
|
-
|
|
318
|
+
hmgr unlink <skill> auf ein einzelnes Mitglied nimmt es aus dem Bundle heraus: nur dieser Link
|
|
319
|
+
verschwindet, das Bundle bleibt im Ziel und merkt sich den Skill als herausgenommen. sync und
|
|
320
|
+
update legen ihn nicht wieder an, neue Mitglieder der Definition ergänzen sie weiter. Zurück kommt
|
|
321
|
+
er mit hmgr link <skill> desselben Skills aus derselben Quelle oder mit bundle sync --complete, das
|
|
322
|
+
alle fehlenden Mitglieder verlinkt. remove nimmt die noch verlinkten Mitglieder weg, auch wenn
|
|
323
|
+
schon welche herausgenommen sind. hmgr status und bundle list zeigen die Lage je Ziel, etwa
|
|
324
|
+
„4/5 … fehlt: x".
|
|
321
325
|
|
|
322
326
|
Den Abgleich macht schon hmgr update für alle installierten Bundles mit, es ist derselbe Vorgang
|
|
323
327
|
und dieselbe Ausgabe (E69): eine geänderte Definition kommt also mit dem gewöhnlichen
|
|
@@ -335,11 +339,14 @@ Schalter (add, remove und sync):
|
|
|
335
339
|
kennt nur hermes, wsl:<distro> nur claude-code unter Windows (E78)
|
|
336
340
|
--composer <pfad> composer.json des Arbeitsverzeichnisses, wenn mehrere in Frage kommen
|
|
337
341
|
--quelle <teil> nur bei add: Quelle eingrenzen, wenn den Namen mehrere Quellen führen
|
|
342
|
+
--complete nur bei sync: auch herausgenommene Mitglieder verlinken (Vervollständigen),
|
|
343
|
+
die Liste der herausgenommenen ist danach leer. Auch --vervollstaendigen
|
|
338
344
|
|
|
339
345
|
Beispiele:
|
|
340
346
|
hmgr bundle list
|
|
341
347
|
hmgr bundle add wordpress --ort dir:.
|
|
342
348
|
hmgr bundle sync
|
|
349
|
+
hmgr bundle sync wordpress --ort dir:. --complete
|
|
343
350
|
hmgr bundle remove wordpress --ort dir:.
|
|
344
351
|
|
|
345
352
|
Häufige Fälle:
|
package/dist/cli/main.js
CHANGED
|
@@ -125,7 +125,7 @@ const SCHALTER = {
|
|
|
125
125
|
unlink: { werte: ['harness', 'ort', 'composer'], flaggen: ['local', 'lokal'] },
|
|
126
126
|
adopt: { werte: ['harness', 'ort', 'composer'], flaggen: ['local', 'lokal', 'probelauf'] },
|
|
127
127
|
plugin: { werte: ['harness', 'ort', 'composer', 'quelle'], flaggen: ['local', 'lokal'] },
|
|
128
|
-
bundle: { werte: ['harness', 'ort', 'composer', 'quelle'], flaggen: [] },
|
|
128
|
+
bundle: { werte: ['harness', 'ort', 'composer', 'quelle'], flaggen: ['complete', 'vervollstaendigen'] },
|
|
129
129
|
mcp: { werte: ['harness', 'ort'], flaggen: [] },
|
|
130
130
|
sync: { werte: [], flaggen: [] },
|
|
131
131
|
update: { werte: ['quelle'], flaggen: [] },
|
|
@@ -160,7 +160,8 @@ const UNTERKOMMANDOS = {
|
|
|
160
160
|
add: { woerter: 2, schalter: ['harness', 'ort', 'composer', 'quelle'] },
|
|
161
161
|
remove: { woerter: 2, schalter: ['harness', 'ort', 'composer'] },
|
|
162
162
|
// sync nimmt einen Bundle-Namen, aber keinen zwingend: ohne Namen gilt der ganze Bestand.
|
|
163
|
-
|
|
163
|
+
// --complete/--vervollstaendigen holt herausgenommene Mitglieder zurück (E114 L4).
|
|
164
|
+
sync: { woerter: 2, schalter: ['harness', 'ort', 'composer', 'complete', 'vervollstaendigen'] },
|
|
164
165
|
list: { woerter: 1, schalter: [] },
|
|
165
166
|
},
|
|
166
167
|
mcp: {
|
|
@@ -491,9 +492,10 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
491
492
|
if (kommando === 'unlink') {
|
|
492
493
|
const ergebnis = await anwendungsfaelle.linkEntfernen({ skill, ziel, lokal });
|
|
493
494
|
console.log(`Link ${skill} entfernt.`);
|
|
494
|
-
//
|
|
495
|
-
for (const bundle of ergebnis.
|
|
496
|
-
console.log(
|
|
495
|
+
// Herausgenommen (E114 L2): das Bundle bleibt, der Abgleich legt den Skill nicht wieder an.
|
|
496
|
+
for (const bundle of ergebnis.herausgenommenAus)
|
|
497
|
+
console.log(`„${skill}" ist aus dem Bundle „${bundle}" herausgenommen, das Bundle bleibt. ` +
|
|
498
|
+
`Zurück mit hmgr link ${skill} oder hmgr bundle sync ${bundle} --complete.`);
|
|
497
499
|
if (ergebnis.hinweis !== undefined)
|
|
498
500
|
console.log(ergebnis.hinweis);
|
|
499
501
|
return 0;
|
|
@@ -612,10 +614,15 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
612
614
|
if (kommando === 'bundle') {
|
|
613
615
|
const schalter = schalterLesen(argv.slice(1), 'bundle');
|
|
614
616
|
unterkommandoPruefen('bundle', schalter);
|
|
615
|
-
const { rest, werte } = schalter;
|
|
617
|
+
const { rest, werte, flaggen } = schalter;
|
|
616
618
|
const unterkommando = rest[0];
|
|
617
619
|
if (unterkommando === 'list') {
|
|
618
620
|
const katalog = await anwendungsfaelle.bundleKatalog();
|
|
621
|
+
// Je Bundle die Ziele, in denen es liegt, mit seiner Lage (E114 L6). Nur nötig, wenn
|
|
622
|
+
// überhaupt ein Bundle installiert ist; der Ist-Zustand kostet sonst einen Scan aller Ziele.
|
|
623
|
+
const installiert = (await ports.zustand.lesen()).bundleInstallationen.length > 0
|
|
624
|
+
? (await anwendungsfaelle.istZustand({ plugins: false })).flatMap((z) => z.bundles.map((b) => ({ ziel: z.ziel, bundle: b })))
|
|
625
|
+
: [];
|
|
619
626
|
const leer = katalog.every((k) => k.bundles.length === 0 && k.kaputte.length === 0 && k.fehler === undefined);
|
|
620
627
|
if (leer)
|
|
621
628
|
console.log('Keine Quelle mit Bundles. hmgr help bundle zeigt das Format von bundles/<name>.yaml.');
|
|
@@ -631,6 +638,9 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
631
638
|
console.log(` ${bundle.name} ${kappen(bundle.beschreibung)}`);
|
|
632
639
|
for (const mitglied of bundle.mitglieder)
|
|
633
640
|
console.log(` ${mitglied.pfad} aus ${quelleAlsText(mitglied.quelle)}`);
|
|
641
|
+
for (const { ziel, bundle: lage } of installiert)
|
|
642
|
+
if (lage.name === bundle.name && quelleSchluessel(lage.quelle) === quelleSchluessel(bundle.quelle))
|
|
643
|
+
console.log(` installiert ${ziel.harness} ${beschreibeOrt(ziel.ort)} ${bundleLage(lage)}`);
|
|
634
644
|
}
|
|
635
645
|
// Eine kaputte Definition verdeckt die übrigen nicht, sie wird eigens genannt (E69).
|
|
636
646
|
for (const kaputt of eintrag.kaputte)
|
|
@@ -683,9 +693,11 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
683
693
|
}
|
|
684
694
|
// sync: ohne Ziel-Schalter der ganze Bestand, mit --ort/--harness nur dieses Ziel.
|
|
685
695
|
const nurZiel = werte.has('harness') || werte.has('ort');
|
|
696
|
+
const vervollstaendigen = flaggen.has('complete') || flaggen.has('vervollstaendigen');
|
|
686
697
|
const eintraege = await anwendungsfaelle.bundleAbgleich({
|
|
687
698
|
...(name === undefined ? {} : { bundle: name }),
|
|
688
699
|
...(nurZiel ? { ziel } : {}),
|
|
700
|
+
...(vervollstaendigen ? { aufnehmen: 'alle' } : {}),
|
|
689
701
|
});
|
|
690
702
|
if (eintraege.length === 0)
|
|
691
703
|
console.log('Kein Bundle installiert, nichts abzugleichen.');
|
|
@@ -702,7 +714,10 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
702
714
|
const uebersicht = await anwendungsfaelle.mcpUebersicht();
|
|
703
715
|
if (uebersicht.katalog.length === 0)
|
|
704
716
|
console.log('Kein MCP im Katalog. hmgr help mcp zeigt das Format von ~/.hmgr/mcp.yaml.');
|
|
705
|
-
|
|
717
|
+
// E113: alphabetisch nach Name (Kopie, die Lieferreihenfolge der Daten bleibt).
|
|
718
|
+
const nachName = (a, b) => a.localeCompare(b, 'de', { sensitivity: 'base' });
|
|
719
|
+
const katalogSortiert = [...uebersicht.katalog].sort((a, b) => nachName(a.eintrag.name, b.eintrag.name));
|
|
720
|
+
for (const { eintrag, eingehaengt, geteilteFundorte } of katalogSortiert) {
|
|
706
721
|
console.log(`${eintrag.name} ${eintrag.beschreibung}`);
|
|
707
722
|
if (eingehaengt.length === 0 && geteilteFundorte.length === 0)
|
|
708
723
|
console.log(' nirgends eingehängt');
|
|
@@ -714,9 +729,9 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
714
729
|
}
|
|
715
730
|
if (uebersicht.unbekannt.length > 0 || uebersicht.unbekannteGeteilteFundorte.length > 0) {
|
|
716
731
|
console.log('Nicht im Katalog, aber eingehängt (hmgr fasst sie nicht an):');
|
|
717
|
-
for (const { ziel, name } of uebersicht.unbekannt)
|
|
732
|
+
for (const { ziel, name } of [...uebersicht.unbekannt].sort((a, b) => nachName(a.name, b.name)))
|
|
718
733
|
console.log(` ${name} ${ziel.harness} ${beschreibeOrt(ziel.ort)}`);
|
|
719
|
-
for (const f of uebersicht.unbekannteGeteilteFundorte)
|
|
734
|
+
for (const f of [...uebersicht.unbekannteGeteilteFundorte].sort((a, b) => nachName(a.name, b.name)))
|
|
720
735
|
console.log(` ${f.name} ${f.ziel.harness} ${beschreibeOrt(f.ziel.ort)} ${f.datei} · Scope ${f.scope}`);
|
|
721
736
|
}
|
|
722
737
|
return 0;
|
|
@@ -885,7 +900,7 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
885
900
|
}
|
|
886
901
|
// Bundles des Ziels (E69), unter den Einträgen: welche Links als Einheit zusammengehören.
|
|
887
902
|
for (const bundle of zielZustand.bundles)
|
|
888
|
-
console.log(` Bundle ${bundle.name} (${quelleAlsText(bundle.quelle)}) ${bundle
|
|
903
|
+
console.log(` Bundle ${bundle.name} (${quelleAlsText(bundle.quelle)}) ${bundleLage(bundle)}`);
|
|
889
904
|
if (zielZustand.plugins !== undefined)
|
|
890
905
|
console.log(` Plugins: ${zielZustand.plugins.length === 0 ? 'keine' : zielZustand.plugins.join(', ')}`);
|
|
891
906
|
}
|
|
@@ -1131,6 +1146,16 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
1131
1146
|
}
|
|
1132
1147
|
throw new Error(`Unbekanntes Kommando „${kommando}". hmgr --help zeigt alle Kommandos.`);
|
|
1133
1148
|
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Lage eines installierten Bundles in einem Ziel (E114 L6), für `status` und `bundle list`:
|
|
1151
|
+
* verlinkt von gesamt, die verlinkten Namen und, wenn etwas fehlt, was.
|
|
1152
|
+
*/
|
|
1153
|
+
function bundleLage(bundle) {
|
|
1154
|
+
const gesamt = bundle.skills.length + bundle.nichtVerlinkt.length;
|
|
1155
|
+
const verlinkt = bundle.skills.length === 0 ? '' : ` ${bundle.skills.join(', ')}`;
|
|
1156
|
+
const fehlt = bundle.nichtVerlinkt.length === 0 ? '' : ` fehlt: ${bundle.nichtVerlinkt.join(', ')}`;
|
|
1157
|
+
return `${bundle.skills.length}/${gesamt}${verlinkt}${fehlt}`;
|
|
1158
|
+
}
|
|
1134
1159
|
/**
|
|
1135
1160
|
* Bericht über den Bundle-Abgleich (E69), gleich für `hmgr bundle sync` und `hmgr update`: je
|
|
1136
1161
|
* Bundle eine Zeile mit seinem Ausgang, darunter, was sich geändert hat. „fehlgeschlagen" heißt
|
package/dist/gui/main.js
CHANGED
|
@@ -174,6 +174,9 @@ function zielZustandSerialisieren(z) {
|
|
|
174
174
|
bundles: z.bundles.map((b) => ({
|
|
175
175
|
name: b.name,
|
|
176
176
|
skills: b.skills,
|
|
177
|
+
// E114 L3: nicht verlinkte Mitglieder (herausgenommen oder von Hand gelöscht).
|
|
178
|
+
nichtVerlinkt: b.nichtVerlinkt,
|
|
179
|
+
herausgenommen: b.herausgenommen,
|
|
177
180
|
quelleText: quelleAlsText(b.quelle),
|
|
178
181
|
quelleName: quelleName(b.quelle),
|
|
179
182
|
})),
|
|
@@ -234,8 +237,10 @@ function registriereIpc() {
|
|
|
234
237
|
return ergebnis;
|
|
235
238
|
}));
|
|
236
239
|
// Bundles aller bekannten Quellen (E69): flach wie der Skill-Katalog, je Bundle seine Quelle und
|
|
237
|
-
//
|
|
238
|
-
//
|
|
240
|
+
// seine Mitglieder als Quelle plus Pfad (E114 L1). Name und Beschreibung eines Mitglieds sucht der
|
|
241
|
+
// Renderer im Skill-Katalog nach (`quelleSchluessel` + `pfad`): eine noch nicht eingerichtete
|
|
242
|
+
// Quelle wird hier nicht gelesen, sonst klonte jedes Öffnen des Dialogs. Kaputte Definitionen
|
|
243
|
+
// kommen als eigene Liste mit, damit die GUI sie nennen kann, statt sie zu verschlucken.
|
|
239
244
|
ipcMain.handle('hmgr:bundles', async () => auffangen(async () => {
|
|
240
245
|
const bundles = [];
|
|
241
246
|
const kaputte = [];
|
|
@@ -244,7 +249,11 @@ function registriereIpc() {
|
|
|
244
249
|
bundles.push({
|
|
245
250
|
name: bundle.name,
|
|
246
251
|
beschreibung: bundle.beschreibung,
|
|
247
|
-
mitglieder: bundle.mitglieder.
|
|
252
|
+
mitglieder: bundle.mitglieder.map((m) => ({
|
|
253
|
+
quelleSchluessel: quelleSchluessel(m.quelle),
|
|
254
|
+
quelleText: quelleAlsText(m.quelle),
|
|
255
|
+
pfad: m.pfad,
|
|
256
|
+
})),
|
|
248
257
|
// Anzeige im Dialog: aus welchen Quellen das Bundle Skills holt, ohne Dubletten.
|
|
249
258
|
quellen: [...new Set(bundle.mitglieder.map((m) => quelleAlsText(m.quelle)))],
|
|
250
259
|
quelleText: quelleAlsText(bundle.quelle),
|
|
@@ -272,6 +281,24 @@ function registriereIpc() {
|
|
|
272
281
|
};
|
|
273
282
|
}));
|
|
274
283
|
ipcMain.handle('hmgr:bundleEntfernen', async (_event, args) => auffangen(async () => anwendungsfaelle.bundleEntfernen({ bundle: args.bundle, ziel: zielAusIpc(args.harness, args.ort) })));
|
|
284
|
+
// Vervollständigen (E114 L4, `aufnehmen: 'alle'`) und „Wieder verlinken" einzelner Mitglieder (L3,
|
|
285
|
+
// Namensliste): der Abgleich dieses einen Bundles in diesem Ziel. Wie bundleEntfernen ohne Zeiger.
|
|
286
|
+
// Der Abgleich meldet einen Fehlschlag im Ergebnis statt zu werfen; hier wird er zum Fehler, damit
|
|
287
|
+
// `rufe` im Renderer ihn zeigt.
|
|
288
|
+
ipcMain.handle('hmgr:bundleAbgleichen', async (_event, args) => auffangen(async () => {
|
|
289
|
+
const eintraege = await anwendungsfaelle.bundleAbgleich({
|
|
290
|
+
bundle: args.bundle,
|
|
291
|
+
quelle: quelleAusText(args.quelleText),
|
|
292
|
+
ziel: zielAusIpc(args.harness, args.ort),
|
|
293
|
+
aufnehmen: args.aufnehmen,
|
|
294
|
+
});
|
|
295
|
+
const eintrag = eintraege[0];
|
|
296
|
+
if (eintrag === undefined)
|
|
297
|
+
throw new Error(`Bundle „${args.bundle}" ist dort nicht installiert.`);
|
|
298
|
+
if (eintrag.ergebnis === 'fehlgeschlagen')
|
|
299
|
+
throw new Error(`Bundle „${args.bundle}" ließ sich nicht vervollständigen: ${eintrag.fehler ?? ''}`);
|
|
300
|
+
return { gelegt: eintrag.gelegt };
|
|
301
|
+
}));
|
|
275
302
|
// Nur die Herkunft, ohne die Quellen zu lesen: der Katalog daneben tut das schon.
|
|
276
303
|
ipcMain.handle('hmgr:quellen', async () => auffangen(async () => (await anwendungsfaelle.quellen()).map((quelle) => ({
|
|
277
304
|
art: quelle.art,
|
|
@@ -858,6 +885,7 @@ function fensterOeffnen() {
|
|
|
858
885
|
// fällt, was ins Ziel kommt, und zeigt je Bundle Beschreibung und Herkunft.
|
|
859
886
|
var dskBundleBoxSichtbar = false;
|
|
860
887
|
var dskBundleText = null;
|
|
888
|
+
var dskBundleZuVorher = null, dskBundleKoerperText = null;
|
|
861
889
|
// Aufklappbereich je Zeile (E92): zu vor dem Klick, danach sichtbar mit der ungekürzten
|
|
862
890
|
// Beschreibung; die Checkbox bleibt unberührt, der Dialog offen.
|
|
863
891
|
var dskKoerperVorher = null;
|
|
@@ -895,6 +923,13 @@ function fensterOeffnen() {
|
|
|
895
923
|
dskBundleBoxSichtbar = document.getElementById('dsk-bundlebox')?.hidden === false;
|
|
896
924
|
dskBundleText = document.querySelector('#dsk-bundles .wahlzeile')?.textContent
|
|
897
925
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
926
|
+
// E114 L1: die Bundle-Wahlzeile klappt auf und zeigt ihre Skills samt Beschreibung.
|
|
927
|
+
var dskBundleKoerper = document.querySelector('#dsk-bundles .wahlzeile .wahlkoerper');
|
|
928
|
+
dskBundleZuVorher = dskBundleKoerper?.hidden ?? null;
|
|
929
|
+
document.querySelector('#dsk-bundles .wahlzeile .aufklappknopf')?.click();
|
|
930
|
+
dskBundleKoerperText = dskBundleKoerper && !dskBundleKoerper.hidden
|
|
931
|
+
? dskBundleKoerper.textContent?.replace(/\\s+/g, ' ').trim() ?? null
|
|
932
|
+
: null;
|
|
898
933
|
document.getElementById('d-skills')?.close();
|
|
899
934
|
}
|
|
900
935
|
// Verlinken-Dialog „Wohin?" (E76): er bietet nur Ziele aktiver Harnesses an. Der Text
|
|
@@ -908,20 +943,33 @@ function fensterOeffnen() {
|
|
|
908
943
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
909
944
|
document.getElementById('d-ziel')?.close();
|
|
910
945
|
}
|
|
911
|
-
// Bundle-Gruppe an der
|
|
912
|
-
//
|
|
913
|
-
|
|
946
|
+
// Bundle-Gruppe an der Claude-Code-Home-Karte (E69, E114): Kopf mit Name, Quelle, Zählung
|
|
947
|
+
// „1 von 2 Skills", „Vervollständigen" und „Entfernen"; darunter zugeklappt die Zeilen
|
|
948
|
+
// aller Mitglieder. „skill-creator" hat die Fixture herausgenommen, es steht als blasse
|
|
949
|
+
// Zeile „nicht verlinkt" mit „Wieder verlinken" in der Gruppe.
|
|
950
|
+
var homeGruppe = Array.from(document.querySelectorAll('#zielliste .ziel'))
|
|
951
|
+
.find((k) => (k.querySelector('.zielkopf')?.textContent || '').indexOf('Claude Code · Home') > -1)
|
|
952
|
+
?.querySelector('.bundlegruppe') ?? null;
|
|
953
|
+
var bundleGruppeText = homeGruppe?.querySelector('.bundlekopf')?.textContent
|
|
914
954
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
915
|
-
var bundleGruppeZeilen = Array.from(
|
|
955
|
+
var bundleGruppeZeilen = Array.from(homeGruppe?.querySelectorAll('.linkliste li:not(.nichtverlinkt) .name') ?? [])
|
|
916
956
|
.map((n) => n.textContent.trim()).join(',');
|
|
917
|
-
|
|
918
|
-
|
|
957
|
+
var bundleNichtVerlinktText = homeGruppe?.querySelector('.linkliste li.nichtverlinkt')?.textContent
|
|
958
|
+
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
959
|
+
var bundleVervollstaendigenKnopf = Array.from(homeGruppe?.querySelectorAll('.bundlekopf button') ?? [])
|
|
960
|
+
.some((k) => k.textContent === 'Vervollständigen');
|
|
961
|
+
var bundleKoerperZuVorher = homeGruppe?.querySelector('.linkliste')?.hidden ?? null;
|
|
962
|
+
homeGruppe?.querySelector('.bundlekopf .aufklappknopf')?.click();
|
|
963
|
+
var bundleKoerperAufNachKlick = homeGruppe?.querySelector('.linkliste')?.hidden === false;
|
|
964
|
+
// Entfernen an der Mitgliedszeile sagt, dass der Skill herausgenommen wird und das
|
|
965
|
+
// Bundle bleibt (E114 L2, früher: zerbricht).
|
|
966
|
+
var bundleHerausnehmenText = null;
|
|
919
967
|
try {
|
|
920
|
-
|
|
921
|
-
|
|
968
|
+
homeGruppe?.querySelector('.linkliste li:not(.nichtverlinkt) .knopf')?.click();
|
|
969
|
+
bundleHerausnehmenText = document.getElementById('dx-text')?.textContent ?? null;
|
|
922
970
|
document.querySelector('#d-entfernen button[value="nein"]')?.click();
|
|
923
971
|
} catch (fehler) {
|
|
924
|
-
|
|
972
|
+
bundleHerausnehmenText = String(fehler);
|
|
925
973
|
}
|
|
926
974
|
// Sammelstreifen unter „Alle" (E95): das Bundle „vorhaben" liegt an kunde-x in Claude Code
|
|
927
975
|
// und Hermes — ein Streifen mit beiden Harness-Zeichen, Entfernen nennt beide Harnesses
|
|
@@ -932,12 +980,21 @@ function fensterOeffnen() {
|
|
|
932
980
|
var streifenZahl = null, streifenHarnesse = null, streifenText = null;
|
|
933
981
|
var streifenDialogTitel = null, streifenDialogText = null;
|
|
934
982
|
var chipGruppeZahl = null, chipGruppeZeilenZahl = null, chipStreifenZahl = null;
|
|
983
|
+
// E114 L1: unter „Alle" stehen die Mitglieder in der Gruppe und nicht zusätzlich in der
|
|
984
|
+
// Tabelle. Name ohne Harness-Zeichen: nur die Textknoten der Namenszelle.
|
|
985
|
+
var nurName = (n) => Array.from(n.childNodes).filter((t) => t.nodeType === 3).map((t) => t.textContent).join('').trim();
|
|
986
|
+
var alleGruppeZeilen = null, alleTabelleZeilen = null;
|
|
935
987
|
try {
|
|
936
988
|
var streifen = Array.from(streifenKarte?.querySelectorAll('.bundlegruppe') ?? []);
|
|
937
989
|
streifenZahl = streifen.length;
|
|
938
990
|
streifenHarnesse = streifen[0]?.querySelector('.zeilenzeichen')?.getAttribute('aria-label') ?? null;
|
|
939
|
-
streifenText = streifen[0]?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
940
|
-
streifen[0]?.
|
|
991
|
+
streifenText = streifen[0]?.querySelector('.bundlekopf')?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
992
|
+
alleGruppeZeilen = Array.from(streifen[0]?.querySelectorAll('.linkliste li .name') ?? []).map(nurName).join(',');
|
|
993
|
+
alleTabelleZeilen = Array.from(streifenKarte?.querySelectorAll('.linkliste li') ?? [])
|
|
994
|
+
.filter((li) => li.closest('.bundlegruppe') === null && li.querySelector('.name'))
|
|
995
|
+
.map((li) => nurName(li.querySelector('.name'))).join(',');
|
|
996
|
+
Array.from(streifen[0]?.querySelectorAll('.bundlekopf button') ?? [])
|
|
997
|
+
.find((k) => k.textContent === 'Entfernen')?.click();
|
|
941
998
|
streifenDialogTitel = document.getElementById('dx-titel')?.textContent ?? null;
|
|
942
999
|
streifenDialogText = document.getElementById('dx-text')?.textContent ?? null;
|
|
943
1000
|
document.querySelector('#d-entfernen button[value="nein"]')?.click();
|
|
@@ -962,6 +1019,8 @@ function fensterOeffnen() {
|
|
|
962
1019
|
document.querySelector('[data-ansicht="mcp"]')?.click();
|
|
963
1020
|
var mcpKartenText = document.getElementById('mcpliste')?.textContent
|
|
964
1021
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
1022
|
+
var mcpKartenNamen = Array.from(document.querySelectorAll('#mcpliste .mcpkopf > b'))
|
|
1023
|
+
.map((b) => b.textContent).join(',');
|
|
965
1024
|
var mcpHeimLinkVorhanden = document.querySelector('#mcpliste .mcpkopf .qlink') !== null;
|
|
966
1025
|
var mcpWarnzeileVorhanden = document.querySelector('#mcpliste .mcp .ruhezeile') !== null;
|
|
967
1026
|
// F46: die Orte-Liste je Karte und der Fremdkasten der Ansicht sind ganz weg, nicht nur
|
|
@@ -1234,13 +1293,21 @@ function fensterOeffnen() {
|
|
|
1234
1293
|
dskAufklappFreiAngehakt,
|
|
1235
1294
|
dskBundleBoxSichtbar,
|
|
1236
1295
|
dskBundleText,
|
|
1296
|
+
dskBundleZuVorher,
|
|
1297
|
+
dskBundleKoerperText,
|
|
1237
1298
|
dzZieleText,
|
|
1238
1299
|
bundleGruppeText,
|
|
1239
1300
|
bundleGruppeZeilen,
|
|
1240
|
-
|
|
1301
|
+
bundleNichtVerlinktText,
|
|
1302
|
+
bundleVervollstaendigenKnopf,
|
|
1303
|
+
bundleKoerperZuVorher,
|
|
1304
|
+
bundleKoerperAufNachKlick,
|
|
1305
|
+
bundleHerausnehmenText,
|
|
1241
1306
|
streifenZahl,
|
|
1242
1307
|
streifenHarnesse,
|
|
1243
1308
|
streifenText,
|
|
1309
|
+
alleGruppeZeilen,
|
|
1310
|
+
alleTabelleZeilen,
|
|
1244
1311
|
streifenDialogTitel,
|
|
1245
1312
|
streifenDialogText,
|
|
1246
1313
|
chipGruppeZahl,
|
|
@@ -1273,6 +1340,7 @@ function fensterOeffnen() {
|
|
|
1273
1340
|
skillOrdnerFehler,
|
|
1274
1341
|
navReihenfolge,
|
|
1275
1342
|
mcpKartenText,
|
|
1343
|
+
mcpKartenNamen,
|
|
1276
1344
|
mcpHeimLinkVorhanden,
|
|
1277
1345
|
mcpWarnzeileVorhanden,
|
|
1278
1346
|
mcpOrteVorhanden,
|
package/dist/gui/preload.cjs
CHANGED
|
@@ -15,6 +15,8 @@ contextBridge.exposeInMainWorld('hmgr', {
|
|
|
15
15
|
bundles: () => ipcRenderer.invoke('hmgr:bundles'),
|
|
16
16
|
bundleInstallieren: (args) => ipcRenderer.invoke('hmgr:bundleInstallieren', args),
|
|
17
17
|
bundleEntfernen: (args) => ipcRenderer.invoke('hmgr:bundleEntfernen', args),
|
|
18
|
+
/** Vervollständigen ('alle') oder einzelne Mitglieder wieder verlinken (E114). */
|
|
19
|
+
bundleAbgleichen: (args) => ipcRenderer.invoke('hmgr:bundleAbgleichen', args),
|
|
18
20
|
/** Icon einer Quelle als data-URL, oder null (E60). */
|
|
19
21
|
icon: (text) => ipcRenderer.invoke('hmgr:icon', text),
|
|
20
22
|
/** Öffnet eine Quelle: Repo-Seite im Browser oder Ordner im Dateimanager (E60). */
|