hmgr 0.0.7 → 0.0.12
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/agents.js +14 -5
- package/dist/adapter/claude-code.js +53 -12
- package/dist/adapter/dateisystem.js +85 -43
- package/dist/adapter/heime.js +76 -0
- package/dist/adapter/hermes.js +16 -7
- package/dist/adapter/npm-registry.js +61 -0
- package/dist/adapter/umgebung.js +6 -1
- package/dist/adapter/verlauf-json.js +39 -0
- package/dist/adapter/wsl.js +212 -0
- package/dist/adapter/zustand-json.js +36 -15
- package/dist/cli/hilfe.js +100 -13
- package/dist/cli/main.js +219 -18
- package/dist/gui/hmgr-cli.js +44 -0
- package/dist/gui/main.js +344 -4
- package/dist/gui/preload.cjs +26 -2
- package/dist/gui/renderer/index.html +67 -15
- package/dist/gui/renderer/renderer.js +441 -228
- package/dist/gui/renderer/styles.css +69 -16
- package/dist/kern/anwendungsfaelle.js +244 -16
- package/dist/kern/modell.js +112 -1
- package/dist/kern/version.js +13 -0
- package/dist/ports/dateizugriff.js +1 -0
- package/dist/ports/harness.js +4 -0
- package/dist/ports/heime.js +1 -0
- package/dist/ports/verlauf.js +4 -0
- package/dist/ports/zustand.js +4 -3
- package/package.json +7 -1
package/dist/cli/main.js
CHANGED
|
@@ -5,19 +5,23 @@ import { realpathSync } from 'node:fs';
|
|
|
5
5
|
import { homedir } from 'node:os';
|
|
6
6
|
import { pathToFileURL } from 'node:url';
|
|
7
7
|
import { Anwendungsfaelle, } from "../kern/anwendungsfaelle.js";
|
|
8
|
-
import { AbhaengigkeitFehlt, BundleDateiFehler, BundleMehrdeutig, BundleMitgliederFehlen, BundleNamenskonflikte, BundleNichtInstalliert, BundleUnbekannt, EinschraenkungOhneZeiger, HarnessNichtVorhanden, HarnessTypUnbekannt, KeinPassenderRef, LinkAnlegenFehlgeschlagen, McpAbweichenderEintrag, McpEbeneNichtUnterstuetzt, McpFaehigkeitFehlt, McpKatalogFehler, McpNichtInGeteilterDatei, McpNurGeteilterFundort, McpUebernahmeNichtMoeglich, McpUebernahmeUnvollstaendig, McpUnbekannt, NameBelegt, OrtNichtUnterstuetzt, PluginMehrdeutig, PluginUnbekannt, QuelleAufraeumenLokaleAenderungen, QuelleNameBelegt, QuelleUnbekannt, SkillMehrdeutig, SkillOrdnerBereitsVerwaltet, SkillOrdnerFaehigkeitFehlt, SkillOrdnerNichtVerwaltet, SkillOrdnerUngueltig, SkillUnbekannt, ZeigerMehrdeutig, ZeigerSchreibenGesperrt, pluginSchluessel, quelleName, quelleSchluessel, } from "../kern/modell.js";
|
|
8
|
+
import { AbhaengigkeitFehlt, BundleDateiFehler, BundleMehrdeutig, BundleMitgliederFehlen, BundleNamenskonflikte, BundleNichtInstalliert, BundleUnbekannt, EinschraenkungOhneZeiger, HarnessInaktiv, HarnessNichtVorhanden, HarnessTypUnbekannt, HeimAdresseUngueltig, HeimBereitsVorhanden, HeimFaehigkeitFehlt, HeimNurUnterWindows, HeimOhneCliZugriff, HeimUnbekannt, KeinPassenderRef, LinkAnlegenFehlgeschlagen, McpAbweichenderEintrag, McpEbeneNichtUnterstuetzt, McpFaehigkeitFehlt, McpKatalogFehler, McpNichtInGeteilterDatei, McpNurGeteilterFundort, McpUebernahmeNichtMoeglich, McpUebernahmeUnvollstaendig, McpUnbekannt, NameBelegt, OrtNichtUnterstuetzt, PluginMehrdeutig, PluginUnbekannt, QuelleAufraeumenLokaleAenderungen, QuelleNameBelegt, QuelleUnbekannt, SkillMehrdeutig, SkillOrdnerBereitsVerwaltet, SkillOrdnerFaehigkeitFehlt, SkillOrdnerNichtVerwaltet, SkillOrdnerUngueltig, SkillUnbekannt, ZeigerMehrdeutig, WslBrueckeFehlgeschlagen, ZeigerSchreibenGesperrt, heimAdresseAlsText, heimAdresseZerlegen, pluginSchluessel, quelleName, quelleSchluessel, } from "../kern/modell.js";
|
|
9
9
|
import { Agents } from "../adapter/agents.js";
|
|
10
|
-
import { ClaudeCode } from "../adapter/claude-code.js";
|
|
10
|
+
import { ClaudeCode, claudeAusfuehrer } from "../adapter/claude-code.js";
|
|
11
11
|
import { Hermes } from "../adapter/hermes.js";
|
|
12
12
|
import { ComposerZeiger } from "../adapter/composer.js";
|
|
13
|
-
import { DateisystemZiele } from "../adapter/dateisystem.js";
|
|
13
|
+
import { DateisystemZiele, LokalerZugriff } from "../adapter/dateisystem.js";
|
|
14
|
+
import { ZustandHeime } from "../adapter/heime.js";
|
|
15
|
+
import { WslBruecke, WslZugriff, wslAusfuehrer, wslDistros } from "../adapter/wsl.js";
|
|
14
16
|
import { GitQuellen } from "../adapter/git.js";
|
|
15
17
|
import { DateiMcpKatalog } from "../adapter/mcp-katalog.js";
|
|
18
|
+
import { cliUpdateHinweis } from "../adapter/npm-registry.js";
|
|
16
19
|
import { paketVersion } from "../adapter/paket-version.js";
|
|
17
20
|
import { quelleAlsText, quelleAusText } from "../adapter/quelle-text.js";
|
|
18
21
|
import { TerminalRueckfrage } from "../adapter/terminal.js";
|
|
19
22
|
import { ProzessUmgebung } from "../adapter/umgebung.js";
|
|
20
23
|
import { ZustandJson } from "../adapter/zustand-json.js";
|
|
24
|
+
import { VerlaufJson } from "../adapter/verlauf-json.js";
|
|
21
25
|
import { HILFE, hilfeText } from "./hilfe.js";
|
|
22
26
|
export function umgebungLesen(env = process.env) {
|
|
23
27
|
const home = env.HOME ?? homedir();
|
|
@@ -30,19 +34,45 @@ export function umgebungLesen(env = process.env) {
|
|
|
30
34
|
}
|
|
31
35
|
export function bauen(umgebung, optionen = {}) {
|
|
32
36
|
const zustand = new ZustandJson(path.join(umgebung.hmgrHome, 'state.json'));
|
|
37
|
+
const verlauf = new VerlaufJson(umgebung.hmgrHome);
|
|
33
38
|
const wurzel = path.join(umgebung.hmgrHome, 'checkouts');
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
const umgebungPort = optionen.umgebung ?? new ProzessUmgebung();
|
|
40
|
+
// Homedirs aus dem Zustand (E78): das primäre lässt sich umstellen (F89), dazu kommen
|
|
41
|
+
// zusätzliche in einer WSL-Distro (F87). `wsl:`-Heime fallen außerhalb von Windows heraus.
|
|
42
|
+
const heime = new ZustandHeime(zustand, umgebung.home, umgebungPort.plattform());
|
|
43
|
+
const wslAusfuehren = optionen.wslAusfuehrer ?? wslAusfuehrer;
|
|
44
|
+
// Je Distro eine Bridge, damit die einmal ermittelte Automount-Wurzel im Lauf erhalten bleibt.
|
|
45
|
+
const bruecken = new Map();
|
|
46
|
+
const bruecke = (distro) => {
|
|
47
|
+
let vorhanden = bruecken.get(distro);
|
|
48
|
+
if (vorhanden === undefined) {
|
|
49
|
+
vorhanden = new WslBruecke(distro, wslAusfuehren);
|
|
50
|
+
bruecken.set(distro, vorhanden);
|
|
51
|
+
}
|
|
52
|
+
return vorhanden;
|
|
53
|
+
};
|
|
54
|
+
const lokal = new LokalerZugriff();
|
|
55
|
+
const zugriffFuerOrt = (ort) => {
|
|
56
|
+
const adresse = ort.art === 'home' ? ort.heim : undefined;
|
|
57
|
+
const zerlegt = adresse === undefined ? undefined : heimAdresseZerlegen(adresse);
|
|
58
|
+
return zerlegt === undefined ? lokal : new WslZugriff(bruecke(zerlegt.distro));
|
|
59
|
+
};
|
|
60
|
+
const claude = new ClaudeCode(heime, optionen.claudeAusfuehrer ?? claudeAusfuehrer, zugriffFuerOrt);
|
|
37
61
|
const ports = {
|
|
38
|
-
harnesses: [claude, new Hermes(
|
|
62
|
+
harnesses: [claude, new Hermes(heime), new Agents(heime)],
|
|
39
63
|
quellen: new GitQuellen(wurzel),
|
|
40
|
-
ziele: new DateisystemZiele(wurzel, zustand, umgebung.xdgStateHome),
|
|
64
|
+
ziele: new DateisystemZiele(wurzel, zustand, umgebung.xdgStateHome, (ziel) => zugriffFuerOrt(ziel.ort)),
|
|
41
65
|
zeiger: new ComposerZeiger(),
|
|
42
66
|
zustand,
|
|
43
67
|
rueckfrage: optionen.rueckfrage ?? new TerminalRueckfrage(),
|
|
44
68
|
mcpKatalog: new DateiMcpKatalog(path.join(umgebung.hmgrHome, 'mcp.yaml')),
|
|
45
|
-
umgebung:
|
|
69
|
+
umgebung: umgebungPort,
|
|
70
|
+
heime,
|
|
71
|
+
wsl: {
|
|
72
|
+
distros: async () => await wslDistros(wslAusfuehren),
|
|
73
|
+
home: async (distro) => await bruecke(distro).home(),
|
|
74
|
+
},
|
|
75
|
+
verlauf,
|
|
46
76
|
};
|
|
47
77
|
return { anwendungsfaelle: new Anwendungsfaelle(ports), ports };
|
|
48
78
|
}
|
|
@@ -65,6 +95,7 @@ const SCHALTER = {
|
|
|
65
95
|
sync: { werte: [], flaggen: [] },
|
|
66
96
|
update: { werte: [], flaggen: [] },
|
|
67
97
|
status: { werte: [], flaggen: [] },
|
|
98
|
+
log: { werte: [], flaggen: [] },
|
|
68
99
|
harness: { werte: ['profil'], flaggen: [] },
|
|
69
100
|
};
|
|
70
101
|
/**
|
|
@@ -165,6 +196,11 @@ function unterkommandoPruefen(kommando, schalter) {
|
|
|
165
196
|
`hmgr help ${kommando} zeigt die Schalter.`);
|
|
166
197
|
restPruefen(schalter.rest, menge.woerter, kommando, unterkommando);
|
|
167
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* `--ort` deuten. Ein zusätzliches Homedir (E78, F87) heißt nach seiner Adresse: `--ort wsl:Ubuntu`,
|
|
201
|
+
* auch in der ausgeschriebenen Form `--ort home:wsl:Ubuntu`. Beides ergibt denselben Ort, damit
|
|
202
|
+
* niemand raten muss, ob das `home:` davor gehört.
|
|
203
|
+
*/
|
|
168
204
|
function ortLesen(text) {
|
|
169
205
|
const roh = text ?? 'home';
|
|
170
206
|
if (roh === 'home')
|
|
@@ -173,7 +209,10 @@ function ortLesen(text) {
|
|
|
173
209
|
return { art: 'arbeitsverzeichnis', pfad: path.resolve(roh.slice(4)) };
|
|
174
210
|
if (roh.startsWith('profil:'))
|
|
175
211
|
return { art: 'profil', name: roh.slice(7) };
|
|
176
|
-
|
|
212
|
+
const heim = heimAdresseZerlegen(roh.startsWith('home:') ? roh.slice(5) : roh);
|
|
213
|
+
if (heim !== undefined)
|
|
214
|
+
return { art: 'home', heim: heimAdresseAlsText(heim) };
|
|
215
|
+
throw new Error(`Unbekannter Ort „${roh}", erwartet home, wsl:<distro>, dir:<pfad> oder profil:<name>`);
|
|
177
216
|
}
|
|
178
217
|
/** Klartext für den Grund, aus dem ein fremder Eintrag liegen bleibt (B12). */
|
|
179
218
|
const UEBERNAHME_GRUND = {
|
|
@@ -217,6 +256,14 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
217
256
|
console.log(text);
|
|
218
257
|
return 0;
|
|
219
258
|
}
|
|
259
|
+
// Versionssprung vermerken (E80): bei jedem echten Kommando, Hilfe und Version sind oben schon
|
|
260
|
+
// zurückgekehrt. Ein Fehler hier (etwa ein kaputtes verlauf.json) darf kein Kommando kippen.
|
|
261
|
+
try {
|
|
262
|
+
await anwendungsfaelle.versionsSprungVermerken('cli', paketVersion(), 'cli');
|
|
263
|
+
}
|
|
264
|
+
catch {
|
|
265
|
+
// still, siehe oben.
|
|
266
|
+
}
|
|
220
267
|
if (kommando === 'source') {
|
|
221
268
|
const schalter = schalterLesen(argv.slice(1), 'source');
|
|
222
269
|
unterkommandoPruefen('source', schalter);
|
|
@@ -668,7 +715,7 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
668
715
|
}
|
|
669
716
|
if (kommando === 'update') {
|
|
670
717
|
restPruefen(schalterLesen(argv.slice(1), 'update').rest, 0, 'update');
|
|
671
|
-
const { checkouts: liste,
|
|
718
|
+
const { checkouts: liste, bundles, aufraeumen } = await anwendungsfaelle.aktualisieren({ ausloeser: 'cli' });
|
|
672
719
|
if (liste.length === 0)
|
|
673
720
|
console.log('Keine Checkouts.');
|
|
674
721
|
for (const { checkout, aktualisierung, geaenderteSkills } of liste) {
|
|
@@ -687,8 +734,6 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
687
734
|
else
|
|
688
735
|
console.log(` fehlgeschlagen ${kopf} ${aktualisierung.fehler}`);
|
|
689
736
|
}
|
|
690
|
-
for (const name of pluginHarnesses)
|
|
691
|
-
console.log(` Plugins ${name} aktualisiert (E14)`);
|
|
692
737
|
// Bundles im selben Lauf (E69, F64=O1): eine geänderte Definition wird hier nachgezogen.
|
|
693
738
|
for (const zeile of bundleBericht(bundles))
|
|
694
739
|
console.log(zeile);
|
|
@@ -706,11 +751,26 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
706
751
|
const geloescht = aufraeumen.verwaiste.filter((v) => v.geloescht).length;
|
|
707
752
|
console.log(`${aufraeumen.verwaiste.length} verwaist, ${geloescht} gelöscht, ${aufraeumen.verwaiste.length - geloescht} liegen geblieben.`);
|
|
708
753
|
}
|
|
754
|
+
// Zuletzt hmgr selbst (E77): wer schon aktualisiert, will auch wissen, dass sein hmgr alt ist.
|
|
755
|
+
// Verglichen wird die eigene Version (E72) gegen npm, gemeldet wird nur — installiert wird
|
|
756
|
+
// nichts. Offline oder Registry unerreichbar heißt keine Zeile, still: der Lauf selbst ist
|
|
757
|
+
// fertig und gelungen, ein fehlgeschlagener Nebenblick darf ihn nicht kommentieren.
|
|
758
|
+
const selbst = await cliUpdateHinweis(paketVersion());
|
|
759
|
+
if (selbst !== null) {
|
|
760
|
+
console.log(selbst.text);
|
|
761
|
+
await anwendungsfaelle.hmgrEreignisVermerken({ art: 'cli-verfuegbar', version: selbst.neu }, 'cli');
|
|
762
|
+
}
|
|
709
763
|
return 0;
|
|
710
764
|
}
|
|
711
765
|
if (kommando === 'status') {
|
|
712
766
|
restPruefen(schalterLesen(argv.slice(1), 'status').rest, 0, 'status');
|
|
713
|
-
|
|
767
|
+
// Ziele inaktiver Harnesses bleiben aus der Liste (E74), auch wenn dort noch Links oder fremde
|
|
768
|
+
// Einträge liegen: was hmgr nicht managed, zeigt es nicht. Gefiltert wird hier, nicht in
|
|
769
|
+
// istZustand — der Kern bleibt ungefiltert (E19), sonst hielte kein Link in einem inaktiven
|
|
770
|
+
// Harness seinen Checkout mehr vor dem Aufräumen.
|
|
771
|
+
const aktiveStatus = new Set(await anwendungsfaelle.aktiveHarnesses());
|
|
772
|
+
const sichtbareZiele = (await anwendungsfaelle.istZustand()).filter((z) => aktiveStatus.has(z.ziel.harness));
|
|
773
|
+
for (const zielZustand of sichtbareZiele) {
|
|
714
774
|
console.log(`Ziel ${zielZustand.ziel.harness} ${beschreibeOrt(zielZustand.ziel.ort)} (${zielZustand.verzeichnis})`);
|
|
715
775
|
if (zielZustand.eintraege.length === 0)
|
|
716
776
|
console.log(' (leer)');
|
|
@@ -737,6 +797,18 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
737
797
|
console.log(`Nicht vorhanden: ${fehlend.join(', ')}`);
|
|
738
798
|
return 0;
|
|
739
799
|
}
|
|
800
|
+
if (kommando === 'log') {
|
|
801
|
+
restPruefen(schalterLesen(argv.slice(1), 'log').rest, 0, 'log');
|
|
802
|
+
const eintraege = await anwendungsfaelle.verlauf();
|
|
803
|
+
if (eintraege.length === 0)
|
|
804
|
+
console.log('Noch keine Ereignisse.');
|
|
805
|
+
for (const eintrag of eintraege) {
|
|
806
|
+
console.log(verlaufZeitpunkt(eintrag.zeit));
|
|
807
|
+
for (const ereignis of eintrag.ereignisse)
|
|
808
|
+
console.log(` ${verlaufEreignisZeile(ereignis)}`);
|
|
809
|
+
}
|
|
810
|
+
return 0;
|
|
811
|
+
}
|
|
740
812
|
if (kommando === 'harness') {
|
|
741
813
|
const schalter = schalterLesen(argv.slice(1), 'harness');
|
|
742
814
|
unterkommandoPruefen('harness', schalter);
|
|
@@ -790,13 +862,83 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
790
862
|
'harness skills-dir <name> add <pfad> oder harness skills-dir <name> remove. ' +
|
|
791
863
|
'hmgr help harness zeigt Beispiele.');
|
|
792
864
|
}
|
|
865
|
+
// Homedirs eines Harness (E78): zeigen, das primäre umstellen (F89), zusätzliche in einer
|
|
866
|
+
// WSL-Distro hinzufügen und entfernen (F87).
|
|
867
|
+
if (unterkommando === 'home') {
|
|
868
|
+
const harnessName = rest[1];
|
|
869
|
+
if (harnessName === undefined)
|
|
870
|
+
throw new Error('harness home braucht einen Harness-Namen, etwa hmgr harness home claude-code. ' +
|
|
871
|
+
'hmgr harness list zeigt die bekannten Namen.');
|
|
872
|
+
const unter = rest[2];
|
|
873
|
+
if (unter === undefined) {
|
|
874
|
+
restPruefen(rest, 2, 'harness', 'home');
|
|
875
|
+
const ansicht = (await anwendungsfaelle.harnessHeime()).find((h) => h.harness === harnessName);
|
|
876
|
+
if (ansicht === undefined)
|
|
877
|
+
throw new HarnessTypUnbekannt(harnessName);
|
|
878
|
+
for (const heim of ansicht.heime) {
|
|
879
|
+
const wie = heim.adresse ?? (heim.eingestellt ? 'home (eingestellt)' : 'home');
|
|
880
|
+
console.log(`${harnessName} ${wie} ${heim.pfad}`);
|
|
881
|
+
}
|
|
882
|
+
if (ansicht.kannZusaetzliche)
|
|
883
|
+
console.log(` Weiteres Homedir: hmgr harness home ${harnessName} add wsl:<distro>.`);
|
|
884
|
+
return 0;
|
|
885
|
+
}
|
|
886
|
+
if (unter === 'set') {
|
|
887
|
+
restPruefen(rest, 4, 'harness', 'home');
|
|
888
|
+
const pfad = rest[3];
|
|
889
|
+
if (pfad === undefined)
|
|
890
|
+
throw new Error('harness home <name> set braucht einen Pfad, etwa hmgr harness home claude-code set D:\\Profile\\tim.');
|
|
891
|
+
const gesetzt = await anwendungsfaelle.harnessHeimSetzen(harnessName, pfad);
|
|
892
|
+
console.log(`${harnessName} liest sein Homedir jetzt unter ${gesetzt}.`);
|
|
893
|
+
console.log(' Was am alten Ort liegt, bleibt dort liegen. hmgr zeigt es nicht mehr.');
|
|
894
|
+
return 0;
|
|
895
|
+
}
|
|
896
|
+
if (unter === 'reset') {
|
|
897
|
+
restPruefen(rest, 3, 'harness', 'home');
|
|
898
|
+
await anwendungsfaelle.harnessHeimZuruecksetzen(harnessName);
|
|
899
|
+
const ansicht = (await anwendungsfaelle.harnessHeime()).find((h) => h.harness === harnessName);
|
|
900
|
+
console.log(`${harnessName} liest sein Homedir wieder unter ${ansicht?.heime[0]?.pfad ?? '?'}.`);
|
|
901
|
+
return 0;
|
|
902
|
+
}
|
|
903
|
+
if (unter === 'add') {
|
|
904
|
+
restPruefen(rest, 4, 'harness', 'home');
|
|
905
|
+
const adresse = rest[3];
|
|
906
|
+
if (adresse === undefined) {
|
|
907
|
+
const distros = await anwendungsfaelle.wslDistros();
|
|
908
|
+
const beispiel = distros[0] ?? 'Ubuntu';
|
|
909
|
+
throw new Error(`harness home <name> add braucht eine Adresse, etwa hmgr harness home ${harnessName} add wsl:${beispiel}.` +
|
|
910
|
+
(distros.length > 0 ? ` Installierte Distros: ${distros.join(', ')}.` : ''));
|
|
911
|
+
}
|
|
912
|
+
const heim = await anwendungsfaelle.harnessHeimHinzufuegen(harnessName, adresse);
|
|
913
|
+
console.log(`${harnessName} ${heim.adresse}: Homedir ${heim.pfad}.`);
|
|
914
|
+
console.log(` Verlinken dorthin mit --harness ${harnessName} --ort ${heim.adresse}.`);
|
|
915
|
+
return 0;
|
|
916
|
+
}
|
|
917
|
+
if (unter === 'remove') {
|
|
918
|
+
restPruefen(rest, 4, 'harness', 'home');
|
|
919
|
+
const adresse = rest[3];
|
|
920
|
+
if (adresse === undefined)
|
|
921
|
+
throw new Error(`harness home <name> remove braucht eine Adresse, etwa hmgr harness home ${harnessName} remove wsl:Ubuntu.`);
|
|
922
|
+
await anwendungsfaelle.harnessHeimEntfernen(harnessName, adresse);
|
|
923
|
+
console.log(`${harnessName} ${adresse}: Homedir vergessen. Die Links dort bleiben liegen.`);
|
|
924
|
+
return 0;
|
|
925
|
+
}
|
|
926
|
+
throw new Error(`Unbekanntes Unterkommando „${unter}" für harness home: harness home <name>, ` +
|
|
927
|
+
'harness home <name> set <pfad>, harness home <name> reset, harness home <name> add wsl:<distro> ' +
|
|
928
|
+
'oder harness home <name> remove wsl:<distro>. hmgr help harness zeigt Beispiele.');
|
|
929
|
+
}
|
|
793
930
|
if (unterkommando === 'list') {
|
|
794
931
|
const aktive = new Set(await anwendungsfaelle.aktiveHarnesses());
|
|
795
932
|
const fehlend = new Set(await anwendungsfaelle.nichtVorhandeneHarnesses());
|
|
933
|
+
const heime = await anwendungsfaelle.harnessHeime();
|
|
796
934
|
for (const name of anwendungsfaelle.harnessTypen()) {
|
|
797
935
|
const aktivText = aktive.has(name) ? 'aktiv' : 'inaktiv';
|
|
798
936
|
const vorhandenText = fehlend.has(name) ? 'nicht vorhanden' : 'vorhanden';
|
|
799
|
-
|
|
937
|
+
// Zusätzliche Homedirs (E78) gehören in die Übersicht: sonst sähe niemand, dass ein
|
|
938
|
+
// zweites Ziel je Harness existiert, ohne extra danach zu fragen.
|
|
939
|
+
const zusatz = (heime.find((h) => h.harness === name)?.heime ?? []).filter((h) => h.adresse !== undefined);
|
|
940
|
+
const heimText = zusatz.length === 0 ? '' : `, ${zusatz.map((h) => h.adresse).join(', ')}`;
|
|
941
|
+
console.log(`${name} ${aktivText}, ${vorhandenText}${heimText}`);
|
|
800
942
|
}
|
|
801
943
|
return 0;
|
|
802
944
|
}
|
|
@@ -845,7 +987,7 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
845
987
|
}
|
|
846
988
|
return 0;
|
|
847
989
|
}
|
|
848
|
-
throw new Error(`${unterkommando === undefined ? 'harness braucht ein Unterkommando' : `Unbekanntes Unterkommando „${unterkommando}" für harness`}: harness list, harness enable <name> oder harness
|
|
990
|
+
throw new Error(`${unterkommando === undefined ? 'harness braucht ein Unterkommando' : `Unbekanntes Unterkommando „${unterkommando}" für harness`}: harness list, harness enable <name>, harness disable <name> oder harness home <name>. hmgr help harness zeigt Beispiele.`);
|
|
849
991
|
}
|
|
850
992
|
throw new Error(`Unbekanntes Kommando „${kommando}". hmgr --help zeigt alle Kommandos.`);
|
|
851
993
|
}
|
|
@@ -874,6 +1016,40 @@ function bundleBericht(eintraege) {
|
|
|
874
1016
|
}
|
|
875
1017
|
return zeilen;
|
|
876
1018
|
}
|
|
1019
|
+
/** Kopfzeile eines Verlaufseintrags (E80): lokale Zeit, damit sie zum Rechner des Lesers passt. */
|
|
1020
|
+
function verlaufZeitpunkt(iso) {
|
|
1021
|
+
const datum = new Date(iso);
|
|
1022
|
+
const zwei = (n) => String(n).padStart(2, '0');
|
|
1023
|
+
return (`${zwei(datum.getDate())}.${zwei(datum.getMonth() + 1)}.${datum.getFullYear()} ` +
|
|
1024
|
+
`${zwei(datum.getHours())}:${zwei(datum.getMinutes())}`);
|
|
1025
|
+
}
|
|
1026
|
+
/** Eine Ereigniszeile im Verlauf (E80), eingerückt unter der Kopfzeile ihres Laufs. */
|
|
1027
|
+
function verlaufEreignisZeile(ereignis) {
|
|
1028
|
+
if (ereignis.art === 'checkout') {
|
|
1029
|
+
const stand = `${ereignis.von.slice(0, 7)} → ${ereignis.nach.slice(0, 7)}`;
|
|
1030
|
+
const skills = ereignis.skills.length > 0 ? `, Skills: ${ereignis.skills.join(', ')}` : '';
|
|
1031
|
+
return `${ereignis.quelle} @ ${ereignis.ref}: ${stand}${skills}`;
|
|
1032
|
+
}
|
|
1033
|
+
if (ereignis.art === 'bundle') {
|
|
1034
|
+
const teile = [
|
|
1035
|
+
ereignis.gelegt.length > 0 ? `gelegt ${ereignis.gelegt.join(', ')}` : undefined,
|
|
1036
|
+
ereignis.entfernt.length > 0 ? `entfernt ${ereignis.entfernt.join(', ')}` : undefined,
|
|
1037
|
+
].filter((t) => t !== undefined);
|
|
1038
|
+
// Formatierung wie in bundleBericht (Harness + beschreibeOrt); ein String-Ziel (vor E80-Nachtrag
|
|
1039
|
+
// geschrieben) bleibt unverändert stehen.
|
|
1040
|
+
const ziel = typeof ereignis.ziel === 'string' ? ereignis.ziel : `${ereignis.ziel.harness} ${beschreibeOrt(ereignis.ziel.ort)}`;
|
|
1041
|
+
return `Bundle ${ereignis.bundle} → ${ziel}: ${teile.join('; ')}`;
|
|
1042
|
+
}
|
|
1043
|
+
if (ereignis.art === 'aufgeraeumt')
|
|
1044
|
+
return `Checkout ${ereignis.checkout} aufgeräumt`;
|
|
1045
|
+
if (ereignis.art === 'fehler')
|
|
1046
|
+
return `Fehler ${ereignis.betrifft}: ${ereignis.fehler}`;
|
|
1047
|
+
if (ereignis.art === 'hmgr-installiert')
|
|
1048
|
+
return ereignis.paket === 'gui' ? `hmgr-GUI ${ereignis.version} installiert` : `hmgr ${ereignis.version} installiert`;
|
|
1049
|
+
if (ereignis.art === 'gui-update-geladen')
|
|
1050
|
+
return `GUI-Update ${ereignis.version} geladen`;
|
|
1051
|
+
return `CLI ${ereignis.version} verfügbar`;
|
|
1052
|
+
}
|
|
877
1053
|
/** Grund eines Links als Suffix (E37). „manuell" bleibt stumm, damit die Ausgabe ruhig bleibt. */
|
|
878
1054
|
function beschreibeGrund(grund) {
|
|
879
1055
|
if (grund === undefined || grund.art === 'manuell')
|
|
@@ -888,9 +1064,10 @@ function zahlwort(n, ein, viele) {
|
|
|
888
1064
|
function kappen(text, laenge = 80) {
|
|
889
1065
|
return text.length <= laenge ? text : `${text.slice(0, laenge - 1)}…`;
|
|
890
1066
|
}
|
|
1067
|
+
/** Ort als Text, so geschrieben, wie `--ort` ihn wieder annimmt. */
|
|
891
1068
|
function beschreibeOrt(ort) {
|
|
892
1069
|
if (ort.art === 'home')
|
|
893
|
-
return 'home';
|
|
1070
|
+
return ort.heim === undefined ? 'home' : ort.heim;
|
|
894
1071
|
if (ort.art === 'profil')
|
|
895
1072
|
return `profil:${ort.name}`;
|
|
896
1073
|
return `dir:${ort.pfad}`;
|
|
@@ -904,6 +1081,7 @@ function istModellFehler(fehler) {
|
|
|
904
1081
|
fehler instanceof ZeigerMehrdeutig ||
|
|
905
1082
|
fehler instanceof ZeigerSchreibenGesperrt ||
|
|
906
1083
|
fehler instanceof HarnessNichtVorhanden ||
|
|
1084
|
+
fehler instanceof HarnessInaktiv ||
|
|
907
1085
|
fehler instanceof HarnessTypUnbekannt ||
|
|
908
1086
|
fehler instanceof KeinPassenderRef ||
|
|
909
1087
|
fehler instanceof EinschraenkungOhneZeiger ||
|
|
@@ -931,7 +1109,14 @@ function istModellFehler(fehler) {
|
|
|
931
1109
|
fehler instanceof McpNurGeteilterFundort ||
|
|
932
1110
|
fehler instanceof McpUebernahmeNichtMoeglich ||
|
|
933
1111
|
fehler instanceof McpNichtInGeteilterDatei ||
|
|
934
|
-
fehler instanceof McpUebernahmeUnvollstaendig
|
|
1112
|
+
fehler instanceof McpUebernahmeUnvollstaendig ||
|
|
1113
|
+
fehler instanceof HeimAdresseUngueltig ||
|
|
1114
|
+
fehler instanceof HeimBereitsVorhanden ||
|
|
1115
|
+
fehler instanceof HeimFaehigkeitFehlt ||
|
|
1116
|
+
fehler instanceof HeimNurUnterWindows ||
|
|
1117
|
+
fehler instanceof HeimOhneCliZugriff ||
|
|
1118
|
+
fehler instanceof HeimUnbekannt ||
|
|
1119
|
+
fehler instanceof WslBrueckeFehlgeschlagen);
|
|
935
1120
|
}
|
|
936
1121
|
/**
|
|
937
1122
|
* Der nächste Schritt zu einem Fehler aus dem Kern. Die Fehlertexte selbst bleiben, wie das Modell
|
|
@@ -966,10 +1151,26 @@ function naechsterSchritt(fehler) {
|
|
|
966
1151
|
return 'Die Tags der Quelle sind frisch geholt, keiner passt. Sonst einen vorhandenen Tag- oder Branchnamen als --version nennen.';
|
|
967
1152
|
if (fehler instanceof HarnessNichtVorhanden)
|
|
968
1153
|
return 'Der Harness legt sein Verzeichnis beim ersten Start an. hmgr status zeigt, welche Harnesses hier liegen.';
|
|
1154
|
+
if (fehler instanceof HarnessInaktiv)
|
|
1155
|
+
return `Erst aktivieren: hmgr harness enable ${fehler.harness}. Bestehende Links dort bleiben unberührt.`;
|
|
969
1156
|
if (fehler instanceof OrtNichtUnterstuetzt)
|
|
970
1157
|
return 'profil:<name> kennt nur hermes, claude-code und agents kennen home und dir:<pfad>.';
|
|
971
1158
|
if (fehler instanceof HarnessTypUnbekannt)
|
|
972
1159
|
return 'Bekannt sind claude-code, hermes und agents. hmgr harness list zeigt sie mit ihrem Stand.';
|
|
1160
|
+
if (fehler instanceof HeimAdresseUngueltig)
|
|
1161
|
+
return 'Ein zusätzliches Homedir wird als wsl:<distro> angegeben. Ein abweichender normaler Pfad gehört an hmgr harness home <name> set <pfad>.';
|
|
1162
|
+
if (fehler instanceof HeimFaehigkeitFehlt)
|
|
1163
|
+
return 'Zusätzliche Homedirs kennt bisher nur claude-code. Für einen abweichenden Pfad: hmgr harness home <name> set <pfad>.';
|
|
1164
|
+
if (fehler instanceof HeimNurUnterWindows)
|
|
1165
|
+
return 'Auf diesem Rechner gibt es kein WSL. Das Homedir wird auf dem Windows-Rechner eingetragen, auf dem die Distro läuft.';
|
|
1166
|
+
if (fehler instanceof HeimBereitsVorhanden)
|
|
1167
|
+
return `hmgr harness home ${fehler.harness} zeigt die eingetragenen Homedirs.`;
|
|
1168
|
+
if (fehler instanceof HeimUnbekannt)
|
|
1169
|
+
return `hmgr harness home ${fehler.harness} zeigt die eingetragenen Homedirs, add trägt eines ein.`;
|
|
1170
|
+
if (fehler instanceof HeimOhneCliZugriff)
|
|
1171
|
+
return 'Skill-Links dort legt hmgr selbst: hmgr link <skill> --harness claude-code --ort <adresse>.';
|
|
1172
|
+
if (fehler instanceof WslBrueckeFehlgeschlagen)
|
|
1173
|
+
return 'wsl -l -q zeigt die installierten Distros. Startet die Distro nicht, hilft wsl --shutdown und ein erneuter Versuch.';
|
|
973
1174
|
if (fehler instanceof QuelleUnbekannt)
|
|
974
1175
|
return 'hmgr source list zeigt die bekannten Quellen.';
|
|
975
1176
|
if (fehler instanceof QuelleNameBelegt)
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// Die installierte hmgr-CLI aus Sicht der GUI (E77). Die GUI trägt ihre eigene Version in sich
|
|
2
|
+
// (`paketVersion()`, E72) — die CLI daneben ist ein zweites, unabhängig installiertes Paket, ihre
|
|
3
|
+
// Version steht nur über ihren eigenen Aufruf fest.
|
|
4
|
+
import spawn from 'cross-spawn';
|
|
5
|
+
import { versionLesen } from "../kern/version.js";
|
|
6
|
+
/**
|
|
7
|
+
* `hmgr --version` (E72: nur die Nummer, Exit 0). Null heißt „nichts zu melden": keine CLI im PATH,
|
|
8
|
+
* Fehlercode, Timeout, oder eine Ausgabe, die keine Version ist. Kein Fehler dringt nach außen —
|
|
9
|
+
* eine fehlende CLI ist der Normalfall bei einer reinen GUI-Installation, keine Störung.
|
|
10
|
+
*
|
|
11
|
+
* `spawn` von cross-spawn wie im claude-Adapter (E65/B7): unter Windows ist die npm-installierte
|
|
12
|
+
* `hmgr` ein `.cmd`-Shim, das Node seit dem Fix zu CVE-2024-27980 ohne Umweg über cmd.exe nicht
|
|
13
|
+
* mehr startet. stdin zu und ein Timeout, damit nichts hängen bleibt.
|
|
14
|
+
*/
|
|
15
|
+
export function hmgrCliVersion() {
|
|
16
|
+
return new Promise((aufloesen) => {
|
|
17
|
+
let fertig = false;
|
|
18
|
+
const melden = (wert) => {
|
|
19
|
+
if (fertig)
|
|
20
|
+
return;
|
|
21
|
+
fertig = true;
|
|
22
|
+
aufloesen(wert);
|
|
23
|
+
};
|
|
24
|
+
try {
|
|
25
|
+
const kind = spawn('hmgr', ['--version'], {
|
|
26
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
27
|
+
timeout: 10_000,
|
|
28
|
+
killSignal: 'SIGKILL',
|
|
29
|
+
});
|
|
30
|
+
let stdout = '';
|
|
31
|
+
kind.stdout.on('data', (stueck) => (stdout += stueck));
|
|
32
|
+
kind.on('error', () => melden(null));
|
|
33
|
+
kind.on('close', (code) => {
|
|
34
|
+
if (code !== 0)
|
|
35
|
+
return melden(null);
|
|
36
|
+
const text = stdout.trim().split('\n')[0]?.trim() ?? '';
|
|
37
|
+
melden(versionLesen(text) === null ? null : text);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
melden(null);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|