hmgr 0.0.6 → 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/bundle-yaml.js +87 -0
- package/dist/adapter/claude-code.js +53 -12
- package/dist/adapter/dateisystem.js +85 -43
- package/dist/adapter/git.js +148 -0
- 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/paket-version.js +25 -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 +40 -12
- package/dist/cli/hilfe.js +197 -11
- package/dist/cli/main.js +376 -21
- package/dist/gui/hmgr-cli.js +44 -0
- package/dist/gui/main.js +445 -4
- package/dist/gui/preload.cjs +30 -2
- package/dist/gui/renderer/index.html +79 -16
- package/dist/gui/renderer/renderer.js +807 -286
- package/dist/gui/renderer/styles.css +89 -16
- package/dist/kern/anwendungsfaelle.js +687 -18
- package/dist/kern/modell.js +192 -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 +16 -1
- package/package.json +26 -5
package/dist/kern/modell.js
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
// Begriffe aus CONTEXT.md. Nur Werte und Regeln, keine Pfade zu Dateien außerhalb des Modells.
|
|
2
2
|
import { ortSchluessel, urlOrt } from "./quelle-ort.js";
|
|
3
|
+
/**
|
|
4
|
+
* Identität eines Bundles (E69): Quelle der Definition plus Name. Zwei Quellen dürfen denselben
|
|
5
|
+
* Bundle-Namen führen, mehrdeutig wird es erst beim Suchen, wie bei Skills (E12).
|
|
6
|
+
*/
|
|
7
|
+
export function bundleSchluessel(bundle) {
|
|
8
|
+
return `${quelleSchluessel(bundle.quelle)}#${bundle.name}`;
|
|
9
|
+
}
|
|
3
10
|
/** Ansprache eines Plugins im Zeiger und gegenüber der claude-CLI: `<plugin>@<marketplace>`. */
|
|
4
11
|
export function pluginSchluessel(plugin) {
|
|
5
12
|
return `${plugin.name}@${plugin.marketplace}`;
|
|
@@ -43,9 +50,108 @@ export function marketplaceUrl(quelle) {
|
|
|
43
50
|
}
|
|
44
51
|
export function zielSchluessel(ziel) {
|
|
45
52
|
const o = ziel.ort;
|
|
46
|
-
const ort = o.art === 'home'
|
|
53
|
+
const ort = o.art === 'home'
|
|
54
|
+
? o.heim === undefined
|
|
55
|
+
? 'home'
|
|
56
|
+
: `home:${o.heim}`
|
|
57
|
+
: o.art === 'profil'
|
|
58
|
+
? `profil:${o.name}`
|
|
59
|
+
: `dir:${o.pfad}`;
|
|
47
60
|
return `${ziel.harness}/${ort}`;
|
|
48
61
|
}
|
|
62
|
+
export function heimAdresseZerlegen(text) {
|
|
63
|
+
const roh = text.trim();
|
|
64
|
+
if (!roh.toLowerCase().startsWith('wsl:'))
|
|
65
|
+
return undefined;
|
|
66
|
+
const distro = roh.slice('wsl:'.length).trim();
|
|
67
|
+
if (distro.length === 0)
|
|
68
|
+
return undefined;
|
|
69
|
+
return { art: 'wsl', distro };
|
|
70
|
+
}
|
|
71
|
+
/** Die Adresse eines zusätzlichen Heims in der Schreibweise, die hmgr speichert und anzeigt. */
|
|
72
|
+
export function heimAdresseAlsText(adresse) {
|
|
73
|
+
return `wsl:${adresse.distro}`;
|
|
74
|
+
}
|
|
75
|
+
/** Ein Text, der keine Heim-Adresse ist (E78). */
|
|
76
|
+
export class HeimAdresseUngueltig extends Error {
|
|
77
|
+
adresse;
|
|
78
|
+
constructor(adresse) {
|
|
79
|
+
super(`„${adresse}" ist keine Adresse für ein zusätzliches Homedir. Erwartet wird wsl:<distro>, etwa wsl:Ubuntu.`);
|
|
80
|
+
this.adresse = adresse;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Ein `wsl:`-Heim auf einer Plattform ohne WSL (E78, Entscheidung 7). Steht so eines im Zustand,
|
|
85
|
+
* weil er von einem Windows-Rechner stammt, wird sein Ziel hier nicht angezeigt und nicht bedient;
|
|
86
|
+
* Hinzufügen bricht mit dieser Meldung ab.
|
|
87
|
+
*/
|
|
88
|
+
export class HeimNurUnterWindows extends Error {
|
|
89
|
+
adresse;
|
|
90
|
+
plattform;
|
|
91
|
+
constructor(adresse, plattform) {
|
|
92
|
+
super(`Ein Homedir in WSL („${adresse}") gibt es nur unter Windows, nicht unter ${plattform}.`);
|
|
93
|
+
this.adresse = adresse;
|
|
94
|
+
this.plattform = plattform;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** Ein Harness-Typ ohne die Fähigkeit „zusätzliche Homedirs" (E78): heute nur claude-code hat sie. */
|
|
98
|
+
export class HeimFaehigkeitFehlt extends Error {
|
|
99
|
+
harness;
|
|
100
|
+
constructor(harness) {
|
|
101
|
+
super(`Harness ${harness} kennt keine zusätzlichen Homedirs`);
|
|
102
|
+
this.harness = harness;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Dieselbe Adresse ist für diesen Harness schon eingetragen (E78). */
|
|
106
|
+
export class HeimBereitsVorhanden extends Error {
|
|
107
|
+
harness;
|
|
108
|
+
adresse;
|
|
109
|
+
constructor(harness, adresse) {
|
|
110
|
+
super(`${harness} hat schon ein Homedir „${adresse}"`);
|
|
111
|
+
this.harness = harness;
|
|
112
|
+
this.adresse = adresse;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/** Eine Adresse, die für diesen Harness nicht eingetragen ist (E78): Entfernen kennt nur eingetragene. */
|
|
116
|
+
export class HeimUnbekannt extends Error {
|
|
117
|
+
harness;
|
|
118
|
+
adresse;
|
|
119
|
+
constructor(harness, adresse) {
|
|
120
|
+
super(`${harness} hat kein Homedir „${adresse}"`);
|
|
121
|
+
this.harness = harness;
|
|
122
|
+
this.adresse = adresse;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Etwas, das nur am primären Homedir geht, wurde für ein zusätzliches verlangt (E78): die
|
|
127
|
+
* claude-CLI dieses Rechners bedient das Windows-Home, nicht das einer WSL-Distro — MCP-Server und
|
|
128
|
+
* Plugins lassen sich dort deshalb nicht verwalten. Skill-Links legt hmgr dort selbst, ohne CLI.
|
|
129
|
+
*/
|
|
130
|
+
export class HeimOhneCliZugriff extends Error {
|
|
131
|
+
harness;
|
|
132
|
+
adresse;
|
|
133
|
+
constructor(harness, adresse, was) {
|
|
134
|
+
super(`${harness} kann ${was} im Homedir „${adresse}" nicht verwalten: die claude-CLI dieses Rechners bedient nur ` +
|
|
135
|
+
'das primäre Homedir. Skill-Links legt hmgr dort selbst.');
|
|
136
|
+
this.harness = harness;
|
|
137
|
+
this.adresse = adresse;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Die Bridge in eine WSL-Distro hat nicht geantwortet (E78): die Distro gibt es nicht, sie startet
|
|
142
|
+
* nicht, oder wsl.exe fehlt. Die Ausgabe von wsl.exe steht mit in der Meldung — sie nennt den Grund
|
|
143
|
+
* genauer, als hmgr ihn raten könnte.
|
|
144
|
+
*/
|
|
145
|
+
export class WslBrueckeFehlgeschlagen extends Error {
|
|
146
|
+
distro;
|
|
147
|
+
ausgabe;
|
|
148
|
+
constructor(distro, ausgabe) {
|
|
149
|
+
const zusatz = ausgabe.trim().length === 0 ? '' : `: ${ausgabe.trim()}`;
|
|
150
|
+
super(`wsl.exe -d ${distro} ließ sich nicht ausführen${zusatz}`);
|
|
151
|
+
this.distro = distro;
|
|
152
|
+
this.ausgabe = ausgabe;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
49
155
|
/** Wie eine Quelle geschrieben steht: ihre URL oder ihr Pfad. Für Ausgaben, nicht für Vergleiche. */
|
|
50
156
|
export function quelleAlsText(quelle) {
|
|
51
157
|
return quelle.art === 'git' ? quelle.url : quelle.pfad;
|
|
@@ -279,6 +385,18 @@ export class HarnessNichtVorhanden extends Error {
|
|
|
279
385
|
this.harness = harness;
|
|
280
386
|
}
|
|
281
387
|
}
|
|
388
|
+
/**
|
|
389
|
+
* Ziel eines deaktivierten Harness beim Anlegen eines Links (E76). Seit E74 zeigt keine Ansicht
|
|
390
|
+
* solche Ziele, ein dort neu gelegter Link wäre unsichtbarer Zustand. Bestehende Links bleiben
|
|
391
|
+
* unberührt, nur das Neuanlegen ist gesperrt.
|
|
392
|
+
*/
|
|
393
|
+
export class HarnessInaktiv extends Error {
|
|
394
|
+
harness;
|
|
395
|
+
constructor(harness) {
|
|
396
|
+
super(`Harness ${harness} ist deaktiviert, hmgr legt dort keine Links an`);
|
|
397
|
+
this.harness = harness;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
282
400
|
/** Ein Name, den kein Harness-Typ trägt: Aktivieren, Deaktivieren und Säubern kennen nur bekannte Typen (E38). */
|
|
283
401
|
export class HarnessTypUnbekannt extends Error {
|
|
284
402
|
harness;
|
|
@@ -448,6 +566,79 @@ export class McpUebernahmeUnvollstaendig extends Error {
|
|
|
448
566
|
this.datei = datei;
|
|
449
567
|
}
|
|
450
568
|
}
|
|
569
|
+
/** Ein Bundle-Name, den keine bekannte Quelle führt (E69). */
|
|
570
|
+
export class BundleUnbekannt extends Error {
|
|
571
|
+
bundleName;
|
|
572
|
+
constructor(bundleName) {
|
|
573
|
+
super(`Bundle „${bundleName}" steht in keiner Quelle`);
|
|
574
|
+
this.bundleName = bundleName;
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
/** Denselben Bundle-Namen führen mehrere Quellen (E69, Regel wie E12 bei Skills). */
|
|
578
|
+
export class BundleMehrdeutig extends Error {
|
|
579
|
+
bundleName;
|
|
580
|
+
quellen;
|
|
581
|
+
constructor(bundleName, quellen) {
|
|
582
|
+
super(`Bundle „${bundleName}" liegt in mehreren Quellen: ${quellen.map(quelleSchluessel).join(', ')}`);
|
|
583
|
+
this.bundleName = bundleName;
|
|
584
|
+
this.quellen = quellen;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
/**
|
|
588
|
+
* Die Definition nennt Mitglieder, die sich auf dieser Maschine nicht auflösen lassen (E69, F66b):
|
|
589
|
+
* eine Quelle ohne Zugriff oder ein Pfad, der in ihr kein Skill ist. Ein halbes Bundle wäre stilles
|
|
590
|
+
* Fehlen von Skills, die falsche Fehlersorte (B13) — deshalb wird abgebrochen, bevor irgendetwas
|
|
591
|
+
* verlinkt ist, und bevor eine fehlende Quelle in den Zustand kommt.
|
|
592
|
+
*/
|
|
593
|
+
export class BundleMitgliederFehlen extends Error {
|
|
594
|
+
bundleName;
|
|
595
|
+
fehler;
|
|
596
|
+
constructor(bundleName, fehler) {
|
|
597
|
+
const zeilen = fehler.map((f) => ` ${f.adresse} (${f.pfad}): ${f.grund}`).join('\n');
|
|
598
|
+
super(`Bundle „${bundleName}" ist auf dieser Maschine nicht vollständig herstellbar, nichts wurde verlinkt:\n${zeilen}`);
|
|
599
|
+
this.bundleName = bundleName;
|
|
600
|
+
this.fehler = fehler;
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
/**
|
|
604
|
+
* Am Ziel liegt unter dem Namen eines Mitglieds schon etwas anderes (E69, F67): ein anderer Skill
|
|
605
|
+
* gleichen Namens, ein fremder Eintrag oder ein Link, der zu einem anderen Bundle gehört. Derselbe
|
|
606
|
+
* Skill aus derselben Quelle ist kein Konflikt, er wird als Mitglied übernommen. Abbruch wie bei
|
|
607
|
+
* `BundleMitgliederFehlen`, die Meldung listet alle Konflikte.
|
|
608
|
+
*/
|
|
609
|
+
export class BundleNamenskonflikte extends Error {
|
|
610
|
+
bundleName;
|
|
611
|
+
ziel;
|
|
612
|
+
konflikte;
|
|
613
|
+
constructor(bundleName, ziel, konflikte) {
|
|
614
|
+
const zeilen = konflikte.map((k) => ` ${k.name}: ${k.grund}`).join('\n');
|
|
615
|
+
super(`Bundle „${bundleName}" lässt sich in ${zielSchluessel(ziel)} nicht anlegen, nichts wurde verlinkt:\n${zeilen}`);
|
|
616
|
+
this.bundleName = bundleName;
|
|
617
|
+
this.ziel = ziel;
|
|
618
|
+
this.konflikte = konflikte;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
/** Ein Bundle, das in diesem Ziel nicht installiert ist (E69): Entfernen kennt nur installierte. */
|
|
622
|
+
export class BundleNichtInstalliert extends Error {
|
|
623
|
+
bundleName;
|
|
624
|
+
ziel;
|
|
625
|
+
constructor(bundleName, ziel) {
|
|
626
|
+
super(`In ${zielSchluessel(ziel)} ist kein Bundle „${bundleName}" installiert`);
|
|
627
|
+
this.bundleName = bundleName;
|
|
628
|
+
this.ziel = ziel;
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
/**
|
|
632
|
+
* Eine Bundle-Definition lässt sich nicht lesen (E69): kaputtes YAML oder ein Feld außerhalb des
|
|
633
|
+
* dokumentierten Formats. Wie beim MCP-Katalog (E61) mit Datei, Feld und Grund in der Meldung.
|
|
634
|
+
*/
|
|
635
|
+
export class BundleDateiFehler extends Error {
|
|
636
|
+
datei;
|
|
637
|
+
constructor(datei, grund) {
|
|
638
|
+
super(`Bundle-Datei ${datei}: ${grund}`);
|
|
639
|
+
this.datei = datei;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
451
642
|
/** Der MCP-Katalog ~/.hmgr/mcp.yaml lässt sich nicht lesen (E61): kaputtes YAML oder falsches Format. */
|
|
452
643
|
export class McpKatalogFehler extends Error {
|
|
453
644
|
pfad;
|
package/dist/kern/version.js
CHANGED
|
@@ -78,6 +78,19 @@ export function vergleichen(a, b) {
|
|
|
78
78
|
}
|
|
79
79
|
return 0;
|
|
80
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Ist `neu` eine höhere Version als `alt`? Für den Update-Hinweis (E77): die von npm gemeldete
|
|
83
|
+
* Version gegen die installierte. Verglichen wird numerisch je Stelle, nie als Text — sonst stünde
|
|
84
|
+
* „0.0.10" unter „0.0.9". Was sich nicht als Version lesen lässt, gilt als nicht neuer: ein
|
|
85
|
+
* unverständlicher Text darf nie zu einer Meldung führen, die zum Update auffordert.
|
|
86
|
+
*/
|
|
87
|
+
export function versionIstNeuer(neu, alt) {
|
|
88
|
+
const a = versionLesen(neu.trim());
|
|
89
|
+
const b = versionLesen(alt.trim());
|
|
90
|
+
if (a === null || b === null)
|
|
91
|
+
return false;
|
|
92
|
+
return vergleichen(a, b) > 0;
|
|
93
|
+
}
|
|
81
94
|
/**
|
|
82
95
|
* Tilde: „`~1.2` ist gleichbedeutend mit `>=1.2 <2.0.0`, `~1.2.3` mit `>=1.2.3 <1.3.0`", die
|
|
83
96
|
* am weitesten rechts genannte Stelle darf wachsen (getcomposer.org, Writing Version Constraints).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/ports/harness.js
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
/** Ob dieser Harness-Typ zusätzliche Homedirs bedienen kann (E78). Ohne die Fähigkeit: nein. */
|
|
2
|
+
export function kannZusaetzlicheHeime(h) {
|
|
3
|
+
return h.zusaetzlicheHeime?.() === true;
|
|
4
|
+
}
|
|
1
5
|
export function kannProfile(h) {
|
|
2
6
|
return typeof h.profile === 'function';
|
|
3
7
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/ports/zustand.js
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fassung des Dateiformats. 1 ist alles vor E69 (das Feld fehlt dort und wird beim Lesen ergänzt),
|
|
3
|
+
* 2 kennt `bundleInstallationen`, 3 kennt `harnessHeime` (E78). Bestand läuft unverändert weiter:
|
|
4
|
+
* ein fehlendes Feld ist eine leere Liste, geschrieben wird danach in der aktuellen Fassung.
|
|
5
|
+
*/
|
|
6
|
+
export const ZUSTAND_FASSUNG = 3;
|
|
1
7
|
export function leererZustand() {
|
|
2
|
-
return {
|
|
8
|
+
return {
|
|
9
|
+
fassung: ZUSTAND_FASSUNG,
|
|
10
|
+
quellen: [],
|
|
11
|
+
arbeitsverzeichnisse: [],
|
|
12
|
+
bindungen: [],
|
|
13
|
+
aktiveHarnesses: ['claude-code'],
|
|
14
|
+
ignorierteEintraege: [],
|
|
15
|
+
bundleInstallationen: [],
|
|
16
|
+
harnessHeime: [],
|
|
17
|
+
};
|
|
3
18
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hmgr",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.12",
|
|
4
4
|
"description": "Harness Manager: Skills und Plugins für AI-Harnesses verwalten",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Tim Kaufmann",
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
"gui:app": "npm run build && electron-builder --mac --arm64",
|
|
26
26
|
"gui:app:win": "npm run build && electron-builder --win --x64",
|
|
27
27
|
"gui:install": "npm run build && electron-builder --mac dir --arm64 && ditto release/mac-arm64/hmgr.app /Applications/hmgr.app",
|
|
28
|
+
"release:win": "node scripts/release.ts",
|
|
28
29
|
"test": "vitest run",
|
|
29
30
|
"test:watch": "vitest",
|
|
30
31
|
"type-check": "tsc --noEmit",
|
|
@@ -32,6 +33,7 @@
|
|
|
32
33
|
},
|
|
33
34
|
"dependencies": {
|
|
34
35
|
"cross-spawn": "^7.0.6",
|
|
36
|
+
"electron-updater": "^6.8.9",
|
|
35
37
|
"yaml": "^2.8.0"
|
|
36
38
|
},
|
|
37
39
|
"devDependencies": {
|
|
@@ -44,7 +46,7 @@
|
|
|
44
46
|
},
|
|
45
47
|
"repository": {
|
|
46
48
|
"type": "git",
|
|
47
|
-
"url": "git+https://gitea.timkaufmann.de/
|
|
49
|
+
"url": "git+https://gitea.timkaufmann.de/taquiri/hmgr.git"
|
|
48
50
|
},
|
|
49
51
|
"build": {
|
|
50
52
|
"appId": "de.timkaufmann.hmgr",
|
|
@@ -58,19 +60,38 @@
|
|
|
58
60
|
"package.json"
|
|
59
61
|
],
|
|
60
62
|
"asar": true,
|
|
63
|
+
"publish": {
|
|
64
|
+
"provider": "generic",
|
|
65
|
+
"url": "https://gitea.timkaufmann.de/taquiri/hmgr/releases/download/latest"
|
|
66
|
+
},
|
|
61
67
|
"mac": {
|
|
62
68
|
"category": "public.app-category.developer-tools",
|
|
63
69
|
"icon": "build/icon.icns",
|
|
64
70
|
"target": [
|
|
65
|
-
{
|
|
66
|
-
|
|
71
|
+
{
|
|
72
|
+
"target": "dir",
|
|
73
|
+
"arch": [
|
|
74
|
+
"arm64"
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"target": "zip",
|
|
79
|
+
"arch": [
|
|
80
|
+
"arm64"
|
|
81
|
+
]
|
|
82
|
+
}
|
|
67
83
|
],
|
|
68
84
|
"identity": null
|
|
69
85
|
},
|
|
70
86
|
"win": {
|
|
71
87
|
"icon": "build/icon.ico",
|
|
72
88
|
"target": [
|
|
73
|
-
{
|
|
89
|
+
{
|
|
90
|
+
"target": "nsis",
|
|
91
|
+
"arch": [
|
|
92
|
+
"x64"
|
|
93
|
+
]
|
|
94
|
+
}
|
|
74
95
|
]
|
|
75
96
|
},
|
|
76
97
|
"nsis": {
|