hmgr 0.0.19 → 0.0.20
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/cli/hilfe.js +15 -2
- package/dist/cli/main.js +15 -3
- package/dist/gui/main.js +34 -0
- package/dist/gui/renderer/renderer.js +17 -2
- package/dist/kern/anwendungsfaelle.js +34 -5
- package/package.json +1 -1
package/dist/cli/hilfe.js
CHANGED
|
@@ -31,7 +31,7 @@ hmgr <kommando> [schalter]
|
|
|
31
31
|
mcp migrate <name> MCP-Server aus der geteilten .mcp.json in den privaten Scope übernehmen
|
|
32
32
|
mcp list Katalog-Einträge zeigen, mit wo sie eingehängt sind
|
|
33
33
|
sync [pfad] Ziel auf den Stand seines Zeigers bringen
|
|
34
|
-
update Alle Checkouts aktualisieren
|
|
34
|
+
update Alle Checkouts aktualisieren, mit <skill> oder --quelle nur eine Quelle
|
|
35
35
|
status Ist-Zustand der Ziele
|
|
36
36
|
log Verlauf der letzten Läufe (Changelog)
|
|
37
37
|
doctor Fehlende Arbeitsverzeichnisse finden und Vergessen anbieten
|
|
@@ -446,6 +446,8 @@ Häufige Fälle:
|
|
|
446
446
|
|
|
447
447
|
Siehe auch: hmgr help dir, hmgr help link, hmgr help update, hmgr help harness`;
|
|
448
448
|
const UPDATE = `hmgr update
|
|
449
|
+
hmgr update <skill>
|
|
450
|
+
hmgr update --quelle <teilstring>
|
|
449
451
|
|
|
450
452
|
Holt für jeden Checkout unter ~/.hmgr den neuesten Stand seines Refs und zieht bei Harnesses mit
|
|
451
453
|
Plugin-Fähigkeit deren Plugins nach (E14). Die Links zeigen weiter auf dieselben Pfade und müssen
|
|
@@ -484,10 +486,21 @@ aufgeräumter Checkout, ein Fehler), schreibt update denselben Eintrag auch in ~
|
|
|
484
486
|
nicht im Verlauf: „claude plugin marketplace update" liefert keine Auskunft, ob sich etwas geändert
|
|
485
487
|
hat, eine Zeile dazu wäre geschönt.
|
|
486
488
|
|
|
487
|
-
|
|
489
|
+
Eingeschränkter Lauf (E89): hmgr update <skill> zieht nur die Quelle nach, in der der Skill liegt
|
|
490
|
+
(liegt der Skill in mehreren Quellen, bricht update ab, dann --quelle nutzen). hmgr update --quelle <teilstring> nimmt ein Stück
|
|
491
|
+
von URL, Pfad oder Anzeigenamen der Quelle, Groß- und Kleinschreibung egal; passt keine oder
|
|
492
|
+
mehr als eine, bricht update mit der Liste ab. Beides zusammen geht nicht. Der Lauf umfasst die
|
|
493
|
+
Checkouts dieser Quelle und die Bundles, deren Definition in ihr liegt. Es entfallen: Plugins,
|
|
494
|
+
Aufräumen verwaister Checkouts, der Check auf fehlende Arbeitsverzeichnisse (doctor) sowie alle
|
|
495
|
+
übrigen Quellen und Bundles. Der Verlaufseintrag entsteht wie im vollen Lauf.
|
|
496
|
+
|
|
497
|
+
Schalter:
|
|
498
|
+
--quelle <teilstring> Nur diese Quelle nachziehen (statt <skill>)
|
|
488
499
|
|
|
489
500
|
Beispiel:
|
|
490
501
|
hmgr update
|
|
502
|
+
hmgr update mein-skill
|
|
503
|
+
hmgr update --quelle mein-repo
|
|
491
504
|
|
|
492
505
|
Häufige Fälle:
|
|
493
506
|
„übersprungen … lokale Änderung (E15)": im Checkout liegt eine Änderung, die durch einen Link
|
package/dist/cli/main.js
CHANGED
|
@@ -93,7 +93,7 @@ const SCHALTER = {
|
|
|
93
93
|
bundle: { werte: ['harness', 'ort', 'composer', 'quelle'], flaggen: [] },
|
|
94
94
|
mcp: { werte: ['harness', 'ort'], flaggen: [] },
|
|
95
95
|
sync: { werte: [], flaggen: [] },
|
|
96
|
-
update: { werte: [], flaggen: [] },
|
|
96
|
+
update: { werte: ['quelle'], flaggen: [] },
|
|
97
97
|
status: { werte: [], flaggen: [] },
|
|
98
98
|
log: { werte: [], flaggen: [] },
|
|
99
99
|
doctor: { werte: [], flaggen: [] },
|
|
@@ -715,8 +715,20 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
715
715
|
return 0;
|
|
716
716
|
}
|
|
717
717
|
if (kommando === 'update') {
|
|
718
|
-
|
|
719
|
-
|
|
718
|
+
const { rest: updateRest, werte: updateWerte } = schalterLesen(argv.slice(1), 'update');
|
|
719
|
+
restPruefen(updateRest, 1, 'update');
|
|
720
|
+
const updateSkill = updateRest[0];
|
|
721
|
+
const updateHinweis = updateWerte.get('quelle');
|
|
722
|
+
if (updateSkill !== undefined && updateHinweis !== undefined)
|
|
723
|
+
throw new Error('update nimmt entweder einen Skill oder --quelle, nicht beides. hmgr help update zeigt die Verwendung.');
|
|
724
|
+
// Eingeschränkter Lauf (E89): nur die Quelle des Skills bzw. die genannte, ohne Plugins,
|
|
725
|
+
// Aufräumen und doctor.
|
|
726
|
+
const nurQuelle = updateSkill !== undefined
|
|
727
|
+
? (await anwendungsfaelle.skillFinden(updateSkill)).quelle
|
|
728
|
+
: updateHinweis !== undefined
|
|
729
|
+
? await anwendungsfaelle.quelleZuHinweis(updateHinweis)
|
|
730
|
+
: undefined;
|
|
731
|
+
const { checkouts: liste, bundles, aufraeumen, doctor, } = await anwendungsfaelle.aktualisieren({ ausloeser: 'cli', ...(nurQuelle === undefined ? {} : { quelle: nurQuelle }) });
|
|
720
732
|
if (liste.length === 0)
|
|
721
733
|
console.log('Keine Checkouts.');
|
|
722
734
|
for (const { checkout, aktualisierung, geaenderteSkills } of liste) {
|
package/dist/gui/main.js
CHANGED
|
@@ -676,6 +676,34 @@ function fensterOeffnen() {
|
|
|
676
676
|
if (verlaufBloecke > 0) break;
|
|
677
677
|
}
|
|
678
678
|
var verlaufText = document.getElementById('verlauf')?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
679
|
+
// Nachziehen je Quelle (E89): das Fixture hat im skills-repo einen neuen Upstream-Commit
|
|
680
|
+
// (fixtureAufbauen), den erst ein Lauf für diese Quelle holt. Erst der Knopf der
|
|
681
|
+
// anderen Quelle (kaputt-repo, ohne Checkout): der Verlauf bleibt, wie er ist, obwohl
|
|
682
|
+
// das skills-repo hinterherhinkt. Dann der Knopf des skills-repo: ein neuer Block, der
|
|
683
|
+
// nur diese Quelle nennt.
|
|
684
|
+
var nachziehenFehler = null;
|
|
685
|
+
var nachziehenKnopfZahl = document.querySelectorAll('#quellenliste .nachziehen').length;
|
|
686
|
+
var nachziehenBloeckeStart = document.querySelectorAll('#verlauf .block').length;
|
|
687
|
+
var nachziehenBloeckeNachAnderer = -1;
|
|
688
|
+
var nachziehenBloeckeNachEigener = -1;
|
|
689
|
+
var nachziehenErsterBlock = null;
|
|
690
|
+
try {
|
|
691
|
+
var nachziehenLauf = async (label) => {
|
|
692
|
+
var knopf = document.querySelector('#quellenliste button[aria-label="' + label + '"]');
|
|
693
|
+
if (!knopf) throw new Error('Knopf fehlt: ' + label);
|
|
694
|
+
knopf.click();
|
|
695
|
+
for (var w = 0; w < 100; w++) {
|
|
696
|
+
await new Promise((r) => setTimeout(r, 100));
|
|
697
|
+
if (!document.getElementById('updatestart').disabled) break;
|
|
698
|
+
}
|
|
699
|
+
return document.querySelectorAll('#verlauf .block').length;
|
|
700
|
+
};
|
|
701
|
+
nachziehenBloeckeNachAnderer = await nachziehenLauf('kaputt-repo nachziehen');
|
|
702
|
+
nachziehenBloeckeNachEigener = await nachziehenLauf('skills-repo nachziehen');
|
|
703
|
+
nachziehenErsterBlock = document.querySelector('#verlauf .block')?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
704
|
+
} catch (fehler) {
|
|
705
|
+
nachziehenFehler = String(fehler);
|
|
706
|
+
}
|
|
679
707
|
// E60: Beschreibung in der Ziel-Tabelle (nicht nur im Katalog), „manuell" entfällt,
|
|
680
708
|
// Zahnrad statt Sonne am Einstellungen-Knopf.
|
|
681
709
|
var zielBeschreibung = document.querySelector('#zielliste .linkliste .was')?.textContent ?? null;
|
|
@@ -1149,6 +1177,12 @@ function fensterOeffnen() {
|
|
|
1149
1177
|
verlaufVorhanden,
|
|
1150
1178
|
verlaufText,
|
|
1151
1179
|
verlaufBloecke,
|
|
1180
|
+
nachziehenFehler,
|
|
1181
|
+
nachziehenKnopfZahl,
|
|
1182
|
+
nachziehenBloeckeStart,
|
|
1183
|
+
nachziehenBloeckeNachAnderer,
|
|
1184
|
+
nachziehenBloeckeNachEigener,
|
|
1185
|
+
nachziehenErsterBlock,
|
|
1152
1186
|
zielsucheVorhanden,
|
|
1153
1187
|
zielzahlNachSuche,
|
|
1154
1188
|
zielKartenNachSucheZahl,
|
|
@@ -2629,7 +2629,9 @@
|
|
|
2629
2629
|
standText();
|
|
2630
2630
|
}
|
|
2631
2631
|
|
|
2632
|
-
|
|
2632
|
+
// Mit `quelle` (E89, Knopf „Nachziehen" der Quellenliste) läuft nur diese Quelle, sonst alles.
|
|
2633
|
+
// Bericht, Stand-Zeile und Verlauf sind dieselben wie beim Kringel.
|
|
2634
|
+
async function aktualisierenLauf(ausloeser, quelle) {
|
|
2633
2635
|
var knopf = $('updatestart');
|
|
2634
2636
|
if (knopf.disabled) return;
|
|
2635
2637
|
knopf.disabled = true;
|
|
@@ -2637,7 +2639,9 @@
|
|
|
2637
2639
|
standLaeuft = true;
|
|
2638
2640
|
standText();
|
|
2639
2641
|
var lauf = rufe(function () {
|
|
2640
|
-
|
|
2642
|
+
var args = { rueckfragen: ausloeser !== 'klick', ausloeser: ausloeser };
|
|
2643
|
+
if (quelle) args.quelle = quelle;
|
|
2644
|
+
return window.hmgr.aktualisieren(args);
|
|
2641
2645
|
});
|
|
2642
2646
|
// Jeder Lauf prüft auch hmgr selbst (E80): angestoßen, nicht abgewartet — ein Fund meldet sich
|
|
2643
2647
|
// später von sich aus in der Seitenleiste (onSelbstUpdate).
|
|
@@ -3539,6 +3543,17 @@
|
|
|
3539
3543
|
stift.appendChild(stiftSvg);
|
|
3540
3544
|
stift.addEventListener('click', function () { oeffneQuelleUmbenennen(q); });
|
|
3541
3545
|
knoepfe.appendChild(stift);
|
|
3546
|
+
// Nur diese Quelle nachziehen (E89): wie der Kringel in der Update-Ansicht, aber ohne
|
|
3547
|
+
// Plugins, Aufräumen und übrige Quellen. Der Renderer kennt nur Text und Art (E54), die
|
|
3548
|
+
// Quelle für den Kern baut er daraus.
|
|
3549
|
+
var nachziehen = e('button', 'knopf leise klein nachziehen', 'Nachziehen');
|
|
3550
|
+
nachziehen.type = 'button';
|
|
3551
|
+
nachziehen.setAttribute('aria-label', q.name + ' nachziehen');
|
|
3552
|
+
nachziehen.addEventListener('click', function () {
|
|
3553
|
+
var quelle = q.art === 'lokal' ? { art: 'lokal', pfad: q.text } : { art: 'git', url: q.text };
|
|
3554
|
+
aktualisierenLauf('klick', quelle);
|
|
3555
|
+
});
|
|
3556
|
+
knoepfe.appendChild(nachziehen);
|
|
3542
3557
|
var weg = e('button', 'knopf leise klein', 'Entfernen …');
|
|
3543
3558
|
weg.type = 'button';
|
|
3544
3559
|
weg.setAttribute('aria-label', q.name + ' entfernen');
|
|
@@ -1109,7 +1109,9 @@ export class Anwendungsfaelle {
|
|
|
1109
1109
|
async bundleAbgleich(args) {
|
|
1110
1110
|
const zustand = await this.p.zustand.lesen();
|
|
1111
1111
|
const zielSchl = args?.ziel === undefined ? undefined : zielSchluessel(args.ziel);
|
|
1112
|
+
const quelleSchl = args?.quelle === undefined ? undefined : quelleSchluessel(args.quelle);
|
|
1112
1113
|
const installationen = zustand.bundleInstallationen.filter((i) => (args?.bundle === undefined || i.bundle === args.bundle) &&
|
|
1114
|
+
(quelleSchl === undefined || quelleSchluessel(i.quelle) === quelleSchl) &&
|
|
1113
1115
|
(zielSchl === undefined || zielSchluessel(Anwendungsfaelle.installationZiel(i)) === zielSchl));
|
|
1114
1116
|
const ergebnis = [];
|
|
1115
1117
|
for (const installation of installationen) {
|
|
@@ -1274,6 +1276,22 @@ export class Anwendungsfaelle {
|
|
|
1274
1276
|
if ((await this.bindungFinden(ziel)) !== undefined)
|
|
1275
1277
|
throw new ZeigerSchreibenGesperrt(ziel);
|
|
1276
1278
|
}
|
|
1279
|
+
/**
|
|
1280
|
+
* Die eine geführte Quelle zu einem Teilstring (E89, `hmgr update --quelle`): verglichen wird mit
|
|
1281
|
+
* Schreibweise (URL/Pfad), Schlüssel und Anzeigenamen, Groß- und Kleinschreibung egal. Kein Treffer
|
|
1282
|
+
* und mehrere Treffer sind Fehler, mit der Liste, aus der sich der Nutzer eingrenzen kann.
|
|
1283
|
+
*/
|
|
1284
|
+
async quelleZuHinweis(hinweis) {
|
|
1285
|
+
const quellen = (await this.p.zustand.lesen()).quellen;
|
|
1286
|
+
const klein = hinweis.toLowerCase();
|
|
1287
|
+
const treffer = quellen.filter((q) => [quelleAlsText(q), quelleSchluessel(q), q.name ?? ''].some((t) => t.toLowerCase().includes(klein)));
|
|
1288
|
+
const zeilen = (liste) => liste.map((q) => ` ${quelleAlsText(q)}${q.name === undefined ? '' : ` (${q.name})`}`).join('\n');
|
|
1289
|
+
if (treffer.length === 1)
|
|
1290
|
+
return treffer[0];
|
|
1291
|
+
if (treffer.length === 0)
|
|
1292
|
+
throw new Error(`Keine Quelle passt auf „${hinweis}".${quellen.length === 0 ? '' : `\nBekannte Quellen:\n${zeilen(quellen)}`}`);
|
|
1293
|
+
throw new Error(`Mehrere Quellen passen auf „${hinweis}", bitte eingrenzen:\n${zeilen(treffer)}`);
|
|
1294
|
+
}
|
|
1277
1295
|
/** Skill über alle Quellen suchen. Mehrere Treffer sind nur mit Quellenhinweis erlaubt. */
|
|
1278
1296
|
async skillFinden(name, quelleHinweis) {
|
|
1279
1297
|
const zustand = await this.p.zustand.lesen();
|
|
@@ -1759,11 +1777,18 @@ export class Anwendungsfaelle {
|
|
|
1759
1777
|
* ergeben hat: unveränderte oder übersprungene Checkouts und Bundles ohne Änderung erzeugen
|
|
1760
1778
|
* nichts, ein leerer Lauf bleibt ganz aus dem Changelog. `ausloeser` steht mit im Eintrag, damit
|
|
1761
1779
|
* der Verlauf zeigt, ob ein Fund vom automatischen Lauf, einem Klick oder der CLI kam.
|
|
1780
|
+
*
|
|
1781
|
+
* Mit `quelle` (E89) läuft nur diese geführte Quelle: ihre Checkouts, ihr Katalog-Fetch und die
|
|
1782
|
+
* Bundle-Installationen, deren Definition in ihr liegt. Plugins, Aufräumen verwaister Checkouts
|
|
1783
|
+
* und doctor entfallen (leere Ergebnisse), weil sie den Gesamtbestand betreffen.
|
|
1762
1784
|
*/
|
|
1763
1785
|
async aktualisieren(args) {
|
|
1764
1786
|
const rueckfragen = args?.rueckfragen ?? true;
|
|
1765
1787
|
const ausloeser = args?.ausloeser ?? 'cli';
|
|
1766
|
-
const
|
|
1788
|
+
const nurSchluessel = args?.quelle === undefined ? undefined : quelleSchluessel(args.quelle);
|
|
1789
|
+
const bekannt = new Map((await this.p.zustand.lesen()).quellen
|
|
1790
|
+
.filter((q) => nurSchluessel === undefined || quelleSchluessel(q) === nurSchluessel)
|
|
1791
|
+
.map((q) => [quelleSchluessel(q), q]));
|
|
1767
1792
|
const checkouts = [];
|
|
1768
1793
|
for (const checkout of await this.p.quellen.checkouts()) {
|
|
1769
1794
|
const gefuehrt = bekannt.get(quelleSchluessel(checkout.quelle));
|
|
@@ -1805,7 +1830,7 @@ export class Anwendungsfaelle {
|
|
|
1805
1830
|
}
|
|
1806
1831
|
// Nach den Checkouts die Plugins nachziehen (E14).
|
|
1807
1832
|
const pluginHarnesses = [];
|
|
1808
|
-
for (const harness of await this.vorhandeneHarnesses()) {
|
|
1833
|
+
for (const harness of nurSchluessel !== undefined ? [] : await this.vorhandeneHarnesses()) {
|
|
1809
1834
|
if (!kannPlugins(harness))
|
|
1810
1835
|
continue;
|
|
1811
1836
|
await harness.plugins.aktualisieren();
|
|
@@ -1814,9 +1839,13 @@ export class Anwendungsfaelle {
|
|
|
1814
1839
|
// Bundles vor dem Aufräumen (E69, F64=O1): der Abgleich legt und entfernt Links, und erst
|
|
1815
1840
|
// danach steht fest, in welchen Checkout noch ein Link zeigt. Ein Fehlschlag je Bundle steckt
|
|
1816
1841
|
// in seinem Eintrag, er bricht den Lauf nicht ab — wie eine unerreichbare Quelle (E51).
|
|
1817
|
-
const bundles = await this.bundleAbgleich();
|
|
1818
|
-
const aufraeumen =
|
|
1819
|
-
|
|
1842
|
+
const bundles = await this.bundleAbgleich(args?.quelle === undefined ? undefined : { quelle: args.quelle });
|
|
1843
|
+
const aufraeumen = nurSchluessel !== undefined
|
|
1844
|
+
? { verwaiste: [], gefragt: false }
|
|
1845
|
+
: await this.verwaisteAufraeumen(checkouts, rueckfragen);
|
|
1846
|
+
const doctorErgebnis = nurSchluessel !== undefined
|
|
1847
|
+
? { fehlendeArbeitsverzeichnisse: [], vergessen: [] }
|
|
1848
|
+
: await this.doctor({ rueckfragen });
|
|
1820
1849
|
await this.verlaufVermerken(ausloeser, this.aktualisierungsEreignisse(checkouts, bundles, aufraeumen, doctorErgebnis));
|
|
1821
1850
|
return { checkouts, pluginHarnesses, bundles, aufraeumen, doctor: doctorErgebnis };
|
|
1822
1851
|
}
|