hmgr 0.0.35 → 0.0.36

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.
@@ -51,6 +51,33 @@ export function wslClaudeAusfuehrer(distro, ausfuehren) {
51
51
  return { stdout: ausgabe.toString('utf8'), code };
52
52
  };
53
53
  }
54
+ /** Die Zeile, die dem `env` im Umgebungs-Skript vorausgeht; was davor steht (MOTD, Profil-Echo), ist Rauschen. */
55
+ export const UMGEBUNG_MARKER = '__HMGR_ENV__';
56
+ /**
57
+ * Liest die Umgebung einer Distro (E104): die Login-Shell des Benutzers, interaktiv und als Login
58
+ * (`-lic`), wie sie im Terminal der Distro läuft und `~/.profile` wie `~/.bashrc` liest. Die Shell
59
+ * kann eine MOTD vor die eigene Ausgabe schreiben, deshalb steht der Marker davor.
60
+ */
61
+ export const UMGEBUNG_IN_WSL_SKRIPT = 's=$(getent passwd "$(id -un)" 2>/dev/null | cut -d: -f7); [ -x "$s" ] || s=/bin/sh; ' +
62
+ `exec "$s" -lic 'echo ${UMGEBUNG_MARKER}; env'`;
63
+ /**
64
+ * Die Variablen aus der Ausgabe von `UMGEBUNG_IN_WSL_SKRIPT`: nur was nach der letzten Markerzeile
65
+ * steht, Zeilen `NAME=wert` (Wert darf `=` enthalten). Fortsetzungszeilen mehrzeiliger Werte passen
66
+ * nicht auf das Namensmuster und fallen weg. Ohne Marker: `undefined`.
67
+ */
68
+ export function umgebungLesen(text) {
69
+ const zeilen = text.split(/\r?\n/);
70
+ const ab = zeilen.map((z) => z.trim()).lastIndexOf(UMGEBUNG_MARKER);
71
+ if (ab === -1)
72
+ return undefined;
73
+ const variablen = {};
74
+ for (const zeile of zeilen.slice(ab + 1)) {
75
+ const treffer = /^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/.exec(zeile);
76
+ if (treffer !== null)
77
+ variablen[treffer[1]] = treffer[2];
78
+ }
79
+ return variablen;
80
+ }
54
81
  /**
55
82
  * Eine wsl.exe-eigene Ausgabe als Text (E78, gemessen): UTF-16LE, mit BOM. Node kennt die Kodierung
56
83
  * als „utf16le"; die BOM bleibt beim Dekodieren als `\uFEFF` stehen und wird hier entfernt. Ein
@@ -166,6 +193,14 @@ export class WslBruecke {
166
193
  return null;
167
194
  return { wurzel, relativerPfad: (prefix ?? '').replace(/\/+$/, '') };
168
195
  }
196
+ /**
197
+ * Die Umgebung, die eine im Terminal der Distro gestartete claude sähe (E104); `undefined`, wenn
198
+ * sie nicht lesbar ist (Code ≠ 0, kein Marker, Zeitüberschreitung).
199
+ */
200
+ async variablen() {
201
+ const { text, code } = await this.exec(['sh', '-c', UMGEBUNG_IN_WSL_SKRIPT]);
202
+ return code === 0 ? umgebungLesen(text) : undefined;
203
+ }
169
204
  /** Dasselbe, aber ein Fehlschlag ist kein Fehler: `undefined`. Für lesende Abfragen. */
170
205
  async shWeich(skript) {
171
206
  const { ausgabe, code } = await this.ausfuehren(['-d', this.distro, '/bin/sh', '-c', skript]);
package/dist/cli/hilfe.js CHANGED
@@ -430,7 +430,8 @@ mit der nächsten Sitzung, Hermes lädt seine config.yaml selbst nach, dafür gi
430
430
 
431
431
  Fehlende \${VAR}-Verweise beim Einhängen sind kein Abbruch, nur eine Warnung (F39): hmgr kann nicht
432
432
  wissen, was die Shell beim Start des Harness setzt. Geprüft wird gegen die eigene Prozess-Umgebung
433
- und, bei einem Hermes-Ziel, zusätzlich gegen <hermes-home>/.env.
433
+ und, bei einem Hermes-Ziel, zusätzlich gegen <hermes-home>/.env. Bei einem Ziel in WSL gilt statt der
434
+ Prozess-Umgebung die der Distro, wie ihre Login-Shell sie im Terminal setzt (Login-Shell, interaktiv).
434
435
 
435
436
  Schalter (add, remove und migrate):
436
437
  --harness <name> claude-code oder hermes, Standard claude-code
package/dist/cli/main.js CHANGED
@@ -63,6 +63,8 @@ export function bauen(umgebung, optionen = {}) {
63
63
  // der Bridge, `mcp add-json` startet in der Distro eine ganze Node-Laufzeit.
64
64
  const windowsClaude = optionen.claudeAusfuehrer ?? claudeAusfuehrer;
65
65
  const wslClaudeAusfuehren = optionen.wslAusfuehrer ?? wslAusfuehrerMit(120_000);
66
+ // Die Umgebung der Distro (E104): eine interaktive Login-Shell, die sich nicht melden darf.
67
+ const wslUmgebungAusfuehren = optionen.wslAusfuehrer ?? wslAusfuehrerMit(15_000);
66
68
  const claudeFuerOrt = (ort) => {
67
69
  const distro = wslDistroVonOrt(ort);
68
70
  return distro === undefined ? windowsClaude : wslClaudeAusfuehrer(distro, wslClaudeAusfuehren);
@@ -99,6 +101,7 @@ export function bauen(umgebung, optionen = {}) {
99
101
  distros: async () => await wslDistros(wslAusfuehren),
100
102
  home: async (distro) => await bruecke(distro).home(),
101
103
  gitWurzel: async (distro, linuxPfad) => await bruecke(distro).gitWurzel(linuxPfad),
104
+ variablen: async (distro) => await new WslBruecke(distro, wslUmgebungAusfuehren).variablen(),
102
105
  },
103
106
  verlauf,
104
107
  };
@@ -402,16 +402,30 @@ export class Anwendungsfaelle {
402
402
  const verweise = variablenVerweise(eintrag.konfig);
403
403
  if (verweise.length === 0)
404
404
  return undefined;
405
- const prozessEnv = this.p.umgebung.variablen();
405
+ // Ein WSL-Ziel startet claude in der Distro mit deren Umgebung, nicht mit der von Windows (E104).
406
+ const distro = wslDistroVonOrt(ort);
407
+ let prozessEnv;
408
+ if (distro === undefined) {
409
+ prozessEnv = this.p.umgebung.variablen();
410
+ }
411
+ else {
412
+ const distroEnv = await this.p.wsl.variablen(distro).catch(() => undefined);
413
+ if (distroEnv === undefined) {
414
+ return (`hmgr konnte die Umgebung der WSL-Distro ${distro} nicht lesen; die Verweise ` +
415
+ `${verweise.map((v) => '${' + v + '}').join(', ')} sind deshalb ungeprüft.`);
416
+ }
417
+ prozessEnv = distroEnv;
418
+ }
406
419
  const envPfad = faehig.mcp.envDatei?.(ort);
407
420
  const zusatzEnv = envPfad === undefined ? {} : await this.p.umgebung.envDatei(envPfad);
408
421
  const fehlend = verweise.filter((v) => !(v in prozessEnv) && !(v in zusatzEnv));
409
422
  if (fehlend.length === 0)
410
423
  return undefined;
411
424
  const mehrzahl = fehlend.length > 1;
425
+ const wo = distro === undefined ? 'aktuellen Umgebung' : `Umgebung der WSL-Distro ${distro} (Login-Shell, interaktiv)`;
412
426
  return (`hmgr kann nicht wissen, was die Shell beim Start des Harness setzt: ` +
413
427
  `${mehrzahl ? 'Variablen' : 'Variable'} ${fehlend.join(', ')} ${mehrzahl ? 'sind' : 'ist'} weder in der ` +
414
- 'aktuellen Umgebung noch in einer bekannten .env-Datei zu finden.');
428
+ `${wo} noch in einer bekannten .env-Datei zu finden.`);
415
429
  }
416
430
  /**
417
431
  * MCP einhängen (E61): Katalog-Eintrag an ein Ziel legen, Projekt oder global. Die Fähigkeit hängt
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hmgr",
3
- "version": "0.0.35",
3
+ "version": "0.0.36",
4
4
  "description": "Harness Manager: Skills und Plugins für AI-Harnesses verwalten",
5
5
  "license": "MIT",
6
6
  "author": "Tim Kaufmann",