hmgr 0.0.52 → 0.0.53
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/aenderungen.json +3 -0
- package/dist/cli/hilfe.js +4 -0
- package/dist/cli/main.js +22 -0
- package/dist/gui/main.js +15 -4
- package/dist/gui/preload.cjs +1 -0
- package/dist/gui/renderer/renderer.js +93 -32
- package/dist/gui/renderer/styles.css +2 -12
- package/dist/kern/anwendungsfaelle.js +9 -0
- package/package.json +1 -1
package/dist/aenderungen.json
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"fassung": 1,
|
|
3
3
|
"versionen": {
|
|
4
|
+
"0.0.53": [
|
|
5
|
+
"MCP-Server stehen an der Ordnerkarte jetzt in derselben Tabelle wie die Skills, mit dem Zeichen des Harness davor. Ein Tooltip erklärt, warum ein Server für Hermes fehlt: Hermes liest MCP-Server nur im Home oder in einem Profil, nicht pro Ordner. `hmgr mcp list` sagt das am Ende ebenfalls."
|
|
6
|
+
],
|
|
4
7
|
"0.0.52": [
|
|
5
8
|
"Liegt ein Skill in einem Repo in mehreren Fassungen, je Werkzeug eine (etwa `.claude/skills` und `.hermes/skills`), verlinkt hmgr jetzt für jeden Harness die passende Fassung. Gibt es keine passende, nennt die Meldung die Pfade, und `hmgr link … --pfad` wählt einen aus."
|
|
6
9
|
],
|
package/dist/cli/hilfe.js
CHANGED
|
@@ -424,6 +424,10 @@ global (Scope user). Hermes kennt nur global, mcp_servers in seiner config.yaml
|
|
|
424
424
|
mit --ort profil:<name>); ein Projekt-Ziel ist bei Hermes ein Fehler, es kennt keine Projektebene für
|
|
425
425
|
MCPs. agents kennt MCP-Server gar nicht.
|
|
426
426
|
|
|
427
|
+
Hängt ein Eintrag an einem Arbeitsverzeichnis und ist ein aktiver Harness ohne Projektebene (Hermes) da,
|
|
428
|
+
endet mcp list mit einer Zeile, die sagt, dass dieser Harness den Eintrag dort nicht liest, und auf
|
|
429
|
+
--ort home oder --ort profil:<name> verweist.
|
|
430
|
+
|
|
427
431
|
Bei claude-code führt der Scope local die Server je Git-Repo, nicht je Unterordner (E91). Ein
|
|
428
432
|
Arbeitsverzeichnis, das in einem Repo liegt, ohne dessen Wurzel zu sein, bekommt deshalb kein mcp add,
|
|
429
433
|
mcp remove und mcp migrate: die Meldung nennt den Wurzelordner, dort gehören die Server hin (ist er
|
package/dist/cli/main.js
CHANGED
|
@@ -741,6 +741,28 @@ export async function ausfuehren(argv, umgebung, optionen = {}) {
|
|
|
741
741
|
for (const f of [...uebersicht.unbekannteGeteilteFundorte].sort((a, b) => nachName(a.name, b.name)))
|
|
742
742
|
console.log(` ${f.name} ${f.ziel.harness} ${beschreibeOrt(f.ziel.ort)} ${f.datei} · Scope ${f.scope}`);
|
|
743
743
|
}
|
|
744
|
+
// E120: hängt etwas an einem Arbeitsverzeichnis, erklärt eine Zeile, warum ein aktiver Harness
|
|
745
|
+
// ohne Ordner-MCP (Hermes) es dort nicht hat. Abgeleitet aus den Ebenen der Fähigkeit (E16).
|
|
746
|
+
const anOrdner = [
|
|
747
|
+
...uebersicht.katalog.flatMap((k) => [...k.eingehaengt, ...k.geteilteFundorte.map((g) => g.ziel)]),
|
|
748
|
+
...uebersicht.unbekannt.map((u) => u.ziel),
|
|
749
|
+
...uebersicht.unbekannteGeteilteFundorte.map((u) => u.ziel),
|
|
750
|
+
].some((z) => z.ort.art === 'arbeitsverzeichnis');
|
|
751
|
+
if (anOrdner) {
|
|
752
|
+
const aktive = await anwendungsfaelle.aktiveHarnesses();
|
|
753
|
+
const anzeigeNamen = { 'claude-code': 'Claude Code', hermes: 'Hermes', agents: 'Agents' };
|
|
754
|
+
for (const { harness, ebenen } of anwendungsfaelle.mcpEbenen()) {
|
|
755
|
+
if (!aktive.includes(harness) || ebenen.includes('arbeitsverzeichnis'))
|
|
756
|
+
continue;
|
|
757
|
+
const home = ebenen.includes('home');
|
|
758
|
+
const profil = ebenen.includes('profil');
|
|
759
|
+
if (!home && !profil)
|
|
760
|
+
continue;
|
|
761
|
+
const wo = home && profil ? 'im Home oder in einem Profil' : home ? 'im Home' : 'in einem Profil';
|
|
762
|
+
const orte = [...(home ? ['--ort home'] : []), ...(profil ? ['--ort profil:<name>'] : [])].join(' oder ');
|
|
763
|
+
console.log(`${anzeigeNamen[harness] ?? harness} liest MCP-Server nicht pro Ordner, nur ${wo} (${orte}).`);
|
|
764
|
+
}
|
|
765
|
+
}
|
|
744
766
|
return 0;
|
|
745
767
|
}
|
|
746
768
|
if (unterkommando !== 'add' && unterkommando !== 'remove' && unterkommando !== 'migrate')
|
package/dist/gui/main.js
CHANGED
|
@@ -464,6 +464,7 @@ function registriereIpc() {
|
|
|
464
464
|
}));
|
|
465
465
|
// Plätze für den Einhängen-Dialog (F42): die Fähigkeit hängt am Adapter, nicht am Namen (E16),
|
|
466
466
|
// deshalb kommt die Liste unverändert aus dem Kern statt aus einer Harness-Fallunterscheidung hier.
|
|
467
|
+
ipcMain.handle('hmgr:mcpEbenen', async () => auffangen(async () => anwendungsfaelle.mcpEbenen()));
|
|
467
468
|
ipcMain.handle('hmgr:mcpPlaetze', async () => auffangen(async () => anwendungsfaelle.mcpPlaetze()));
|
|
468
469
|
ipcMain.handle('hmgr:mcpEinhaengen', async (_event, args) => auffangen(async () => mcpWirkungSerialisieren(await anwendungsfaelle.mcpEinhaengen({ name: args.name, ziel: zielAusIpc(args.harness, args.ort) }))));
|
|
469
470
|
ipcMain.handle('hmgr:mcpAushaengen', async (_event, args) => auffangen(async () => mcpWirkungSerialisieren(await anwendungsfaelle.mcpAushaengen({ name: args.name, ziel: zielAusIpc(args.harness, args.ort) }))));
|
|
@@ -997,7 +998,7 @@ function fensterOeffnen() {
|
|
|
997
998
|
streifenHarnesse = streifen[0]?.querySelector('.zeilenzeichen')?.getAttribute('aria-label') ?? null;
|
|
998
999
|
streifenText = streifen[0]?.querySelector('.bundlekopf')?.textContent?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
999
1000
|
alleGruppeZeilen = Array.from(streifen[0]?.querySelectorAll('.linkliste li .name') ?? []).map(nurName).join(',');
|
|
1000
|
-
alleTabelleZeilen = Array.from(streifenKarte?.querySelectorAll('.linkliste li') ?? [])
|
|
1001
|
+
alleTabelleZeilen = Array.from(streifenKarte?.querySelectorAll('.linkliste:not(.mcpzeilen) li') ?? [])
|
|
1001
1002
|
.filter((li) => li.closest('.bundlegruppe') === null && li.querySelector('.name'))
|
|
1002
1003
|
.map((li) => nurName(li.querySelector('.name'))).join(',');
|
|
1003
1004
|
Array.from(streifen[0]?.querySelectorAll('.bundlekopf button') ?? [])
|
|
@@ -1074,7 +1075,7 @@ function fensterOeffnen() {
|
|
|
1074
1075
|
// Seit E64 stehen im MCP-Abschnitt zwei Knopfarten nebeneinander (Entfernen und
|
|
1075
1076
|
// Übernehmen), deshalb wird hier nicht mehr der erste Knopf genommen, sondern der
|
|
1076
1077
|
// Entfernen-Knopf an seinem aria-label erkannt.
|
|
1077
|
-
var mcpZeilenKnoepfe = Array.from(document.querySelectorAll('#zielliste .
|
|
1078
|
+
var mcpZeilenKnoepfe = Array.from(document.querySelectorAll('#zielliste .mcpzeilen button'));
|
|
1078
1079
|
try {
|
|
1079
1080
|
var mcpAusKnopf = mcpZeilenKnoepfe.find(function (b) {
|
|
1080
1081
|
return (b.getAttribute('aria-label') || '').indexOf('aushängen') > -1;
|
|
@@ -1126,13 +1127,20 @@ function fensterOeffnen() {
|
|
|
1126
1127
|
var hermesKarte = karteMitKopftext('Hermes · Home');
|
|
1127
1128
|
var hermesMcpText = hermesKarte?.querySelector('.mcpkarteabschnitt')?.textContent
|
|
1128
1129
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
1129
|
-
var hermesMcpZeilenKnopfZahl = hermesKarte?.querySelectorAll('.
|
|
1130
|
+
var hermesMcpZeilenKnopfZahl = hermesKarte?.querySelectorAll('.mcpzeilen button').length ?? 0;
|
|
1130
1131
|
var hermesMcpKnopfVorhanden = mcpHinzuKnopfAn(hermesKarte) !== undefined;
|
|
1131
1132
|
var kundeXKarte = karteMitKopftext('kunde-x');
|
|
1132
1133
|
var kundeXMcpText = kundeXKarte?.querySelector('.mcpkarteabschnitt')?.textContent
|
|
1133
1134
|
?.replace(/\\s+/g, ' ').trim() ?? null;
|
|
1134
|
-
var kundeXMcpZeilenKnopfZahl = kundeXKarte?.querySelectorAll('.
|
|
1135
|
+
var kundeXMcpZeilenKnopfZahl = kundeXKarte?.querySelectorAll('.mcpzeilen button').length ?? 0;
|
|
1135
1136
|
var kundeXMcpKnopfVorhanden = mcpHinzuKnopfAn(kundeXKarte) !== undefined;
|
|
1137
|
+
// E120: Tabellenkopf des MCP-Abschnitts und die Zeile mail (Katalog, unter „Alle").
|
|
1138
|
+
var kundeXMcpKopf = Array.from(kundeXKarte?.querySelectorAll('.mcpkarteabschnitt .linkkopf .etikett') ?? [])
|
|
1139
|
+
.map((x) => x.textContent).join('|');
|
|
1140
|
+
var kundeXMailZeile = Array.from(kundeXKarte?.querySelectorAll('.mcpzeilen li') ?? [])
|
|
1141
|
+
.find((li) => (li.querySelector('.name')?.textContent || '') === 'mail');
|
|
1142
|
+
var kundeXMailQuelle = kundeXMailZeile?.querySelector('.quelle')?.textContent ?? null;
|
|
1143
|
+
var kundeXMailZeichenTitel = kundeXMailZeile?.querySelector('.zeilenzeichen')?.getAttribute('title') ?? null;
|
|
1136
1144
|
// Kartenkopf-Zahl (E71): der Kopf zählt Skills, gebündelt wie der Körper zeilt. An der
|
|
1137
1145
|
// Verzeichnis-Karte kunde-x hängen dieselben zwei Skills an zwei Harnesses, eine Summe
|
|
1138
1146
|
// über die Abschnitte ergäbe hier 4.
|
|
@@ -1373,6 +1381,9 @@ function fensterOeffnen() {
|
|
|
1373
1381
|
kundeXMcpText,
|
|
1374
1382
|
kundeXMcpZeilenKnopfZahl,
|
|
1375
1383
|
kundeXMcpKnopfVorhanden,
|
|
1384
|
+
kundeXMcpKopf,
|
|
1385
|
+
kundeXMailQuelle,
|
|
1386
|
+
kundeXMailZeichenTitel,
|
|
1376
1387
|
kundeXKopfZahl,
|
|
1377
1388
|
hermesKopfZahl,
|
|
1378
1389
|
hermesWarnzahl,
|
package/dist/gui/preload.cjs
CHANGED
|
@@ -100,6 +100,7 @@ contextBridge.exposeInMainWorld('hmgr', {
|
|
|
100
100
|
mcpUebersicht: () => ipcRenderer.invoke('hmgr:mcpUebersicht'),
|
|
101
101
|
/** Plätze für den Einhängen-Dialog (F42): kommt aus dem Kern, hängt an der Fähigkeit (E16). */
|
|
102
102
|
mcpPlaetze: () => ipcRenderer.invoke('hmgr:mcpPlaetze'),
|
|
103
|
+
mcpEbenen: () => ipcRenderer.invoke('hmgr:mcpEbenen'),
|
|
103
104
|
mcpEinhaengen: (args) => ipcRenderer.invoke('hmgr:mcpEinhaengen', args),
|
|
104
105
|
mcpAushaengen: (args) => ipcRenderer.invoke('hmgr:mcpAushaengen', args),
|
|
105
106
|
/** Übernehmen aus der geteilten .mcp.json in den privaten Scope (E64), nach Bestätigung im Renderer. */
|
|
@@ -339,6 +339,8 @@
|
|
|
339
339
|
// Kern (F42, E16): Grundlage für den MCP-Abschnitt und den „MCP hinzufügen …"-Knopf an den
|
|
340
340
|
// Ziel-Karten — nie am Harness-Namen entschieden, sondern an dieser Liste.
|
|
341
341
|
var MCP_PLAETZE = [];
|
|
342
|
+
// MCP-Ebenen je Harness (E120), aus der Fähigkeit am Adapter: Grundlage der Tooltip-Erklärung.
|
|
343
|
+
var MCP_EBENEN = [];
|
|
342
344
|
var quellenFilter = 'alle';
|
|
343
345
|
// Sortierung der Skills-Rubrik (E79, Richtung E81): hält für die Sitzung wie quellenFilter,
|
|
344
346
|
// übersteht also ladeAlles. SKILLS selbst bleibt unsortiert nach Datum, damit li.dataset.index
|
|
@@ -473,6 +475,7 @@
|
|
|
473
475
|
rufe(function () { return window.hmgr.mcpPlaetze(); }),
|
|
474
476
|
rufe(function () { return window.hmgr.bundles(); }),
|
|
475
477
|
rufe(function () { return window.hmgr.harnessHeime(); }),
|
|
478
|
+
rufe(function () { return window.hmgr.mcpEbenen(); }),
|
|
476
479
|
]);
|
|
477
480
|
// Alter Stand der Verzeichnis-Pfade, vor dem Überschreiben unten (E84 Teil 1): zielKarten()
|
|
478
481
|
// liest hier noch ZIELE/AKTIVE_HARNESSE von vor diesem Lauf. null heißt „kein Vergleich", der
|
|
@@ -495,6 +498,7 @@
|
|
|
495
498
|
BUNDLES.sort(function (a, b) { return a.name.localeCompare(b.name, 'de') || a.quelleText.localeCompare(b.quelleText, 'de'); });
|
|
496
499
|
BUNDLES_KAPUTT = ergebnisse[9].kaputte;
|
|
497
500
|
HARNESS_HEIME = ergebnisse[10] || [];
|
|
501
|
+
MCP_EBENEN = ergebnisse[11] || [];
|
|
498
502
|
STANDARD_REF = {};
|
|
499
503
|
SKILLS.forEach(function (s) { if (STANDARD_REF[s.quelleText] === undefined) STANDARD_REF[s.quelleText] = s.ref; });
|
|
500
504
|
|
|
@@ -1112,54 +1116,115 @@
|
|
|
1112
1116
|
return zeilen;
|
|
1113
1117
|
}
|
|
1114
1118
|
|
|
1115
|
-
/**
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1119
|
+
/** Quelle-Spalte und Beschreibung einer MCP-Zeile (E120, F142). */
|
|
1120
|
+
function mcpQuelleText(row) {
|
|
1121
|
+
if (row.art === 'katalog') return 'Katalog';
|
|
1122
|
+
if (row.art === 'fremd') return 'nicht im Katalog';
|
|
1123
|
+
return '.mcp.json des Projekts';
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/** Tooltip an den Harness-Zeichen einer MCP-Zeile unter „Alle" (E120): wo der Server hier hängt und,
|
|
1127
|
+
je weiterem aktivem Harness des Orts, warum nicht. Der Grund kommt aus den MCP-Ebenen der
|
|
1128
|
+
Fähigkeit (MCP_EBENEN, E16), nie aus dem Harness-Namen. Ein Harness, der den Server hier haben
|
|
1129
|
+
könnte (Ebene arbeitsverzeichnis), bekommt keinen Satz: ein Grund wäre geraten (etwa fehlende
|
|
1130
|
+
CLI, E103). */
|
|
1131
|
+
function mcpZeichenTitel(name, hatHarnesse, teile) {
|
|
1132
|
+
var saetze = ['Hier hängt ' + name + ' für ' + hatHarnesse.map(harnessName).join(', ') + '.'];
|
|
1133
|
+
var gesehen = {};
|
|
1134
|
+
teile.forEach(function (t) {
|
|
1135
|
+
var h = t.ziel.harness;
|
|
1136
|
+
if (gesehen[h] || hatHarnesse.indexOf(h) > -1 || !harnessAktiv(h)) return;
|
|
1137
|
+
gesehen[h] = true;
|
|
1138
|
+
var f = MCP_EBENEN.find(function (x) { return x.harness === h; });
|
|
1139
|
+
if (!f) return;
|
|
1140
|
+
if (f.ebenen.indexOf('arbeitsverzeichnis') > -1) return;
|
|
1141
|
+
if (f.ebenen.length === 0) {
|
|
1142
|
+
saetze.push(harnessName(h) + ' kennt keine MCP-Server.');
|
|
1143
|
+
} else {
|
|
1144
|
+
saetze.push(harnessName(h) + ' liest MCP-Server nicht pro Ordner, nur im Home'
|
|
1145
|
+
+ (f.ebenen.indexOf('profil') > -1 ? ' oder in einem Profil' : '') + '.');
|
|
1146
|
+
}
|
|
1147
|
+
});
|
|
1148
|
+
return saetze.join(' ');
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
/** Der MCP-Abschnitt einer Ziel-Karte (E61-GUI-Nachtrag, E120): eine Tabelle mit denselben Spalten
|
|
1152
|
+
wie die Skill-Tabelle darüber. `ziele` ist ein Ziel (Harness-Chip) oder mehrere (Chip „Alle",
|
|
1153
|
+
`teile` gesetzt: dann stehen die Harness-Zeichen vor dem Namen). Nur, wenn dort etwas
|
|
1154
|
+
eingehängt ist oder der „hinzufügen"-Knopf ohnehin sichtbar wäre (mcpKannAn). Sperrnotiz (E91)
|
|
1155
|
+
und „Noch nichts eingehängt." bleiben eine Zeile über die Breite. */
|
|
1156
|
+
function mcpAbschnitt(ziele, teile) {
|
|
1157
|
+
var alle = teile !== undefined;
|
|
1158
|
+
if (!Array.isArray(ziele)) ziele = [ziele];
|
|
1159
|
+
var notizen = [];
|
|
1160
|
+
var zeilen = [];
|
|
1161
|
+
var kannAn = false;
|
|
1162
|
+
ziele.forEach(function (ziel) {
|
|
1163
|
+
var wurzel = mcpGitWurzel(ziel);
|
|
1164
|
+
if (wurzel !== null) { notizen.push(mcpWurzelNotiz(wurzel)); return; }
|
|
1165
|
+
if (mcpKannAn(ziel)) kannAn = true;
|
|
1166
|
+
mcpZeilenFuerZiel(ziel).forEach(function (row) { row.ziel = ziel; zeilen.push(row); });
|
|
1167
|
+
});
|
|
1168
|
+
if (zeilen.length === 0 && notizen.length === 0 && !kannAn) return null;
|
|
1169
|
+
zeilen.sort(function (a, b) {
|
|
1170
|
+
return a.name.localeCompare(b.name, 'de') || harnessName(a.ziel.harness).localeCompare(harnessName(b.ziel.harness), 'de');
|
|
1171
|
+
});
|
|
1127
1172
|
var abschnitt = e('div', 'mcpkarteabschnitt');
|
|
1128
|
-
abschnitt.appendChild(e('span', 'etikett', 'MCP'));
|
|
1129
1173
|
if (zeilen.length === 0) {
|
|
1130
|
-
abschnitt.appendChild(e('
|
|
1174
|
+
abschnitt.appendChild(e('span', 'etikett', 'MCP'));
|
|
1175
|
+
if (notizen.length === 0) abschnitt.appendChild(e('p', 'ohne mcpkarteleer', 'Noch nichts eingehängt.'));
|
|
1176
|
+
notizen.forEach(function (n) { abschnitt.appendChild(e('p', 'ohne mcpkarteleer', n)); });
|
|
1131
1177
|
return abschnitt;
|
|
1132
1178
|
}
|
|
1133
|
-
var
|
|
1179
|
+
var kopf = e('div', 'linkkopf');
|
|
1180
|
+
kopf.appendChild(e('span'));
|
|
1181
|
+
kopf.appendChild(e('span', 'etikett', 'MCP'));
|
|
1182
|
+
kopf.appendChild(e('span', 'etikett', 'Beschreibung'));
|
|
1183
|
+
kopf.appendChild(e('span', 'etikett', 'Quelle'));
|
|
1184
|
+
kopf.appendChild(e('span'));
|
|
1185
|
+
abschnitt.appendChild(kopf);
|
|
1186
|
+
var ul = e('ul', 'linkliste mcpzeilen');
|
|
1134
1187
|
zeilen.forEach(function (row) {
|
|
1188
|
+
var ziel = row.ziel;
|
|
1135
1189
|
var li = e('li');
|
|
1136
|
-
li.appendChild(e('span', '
|
|
1190
|
+
li.appendChild(e('span', 'repo'));
|
|
1191
|
+
var nameSpan = e('span', 'name');
|
|
1192
|
+
if (alle) {
|
|
1193
|
+
var hat = [];
|
|
1194
|
+
zeilen.forEach(function (r) {
|
|
1195
|
+
if (r.name === row.name && hat.indexOf(r.ziel.harness) === -1) hat.push(r.ziel.harness);
|
|
1196
|
+
});
|
|
1197
|
+
hat.sort(function (a, b) { return harnessName(a).localeCompare(harnessName(b), 'de'); });
|
|
1198
|
+
var zeichen = harnesseZeichenSammel([ziel.harness]);
|
|
1199
|
+
zeichen.title = mcpZeichenTitel(row.name, hat, teile);
|
|
1200
|
+
nameSpan.appendChild(zeichen);
|
|
1201
|
+
}
|
|
1202
|
+
nameSpan.appendChild(document.createTextNode(row.name));
|
|
1203
|
+
li.appendChild(nameSpan);
|
|
1204
|
+
var wasFeld = e('span', 'wasfeld');
|
|
1205
|
+
if (row.art === 'katalog' || row.art === 'geteilt') wasFeld.appendChild(e('span', 'was', row.beschreibung || ''));
|
|
1206
|
+
else if (row.art === 'fremd-geteilt') wasFeld.appendChild(e('span', 'was fehlt', 'nicht im Katalog'));
|
|
1207
|
+
li.appendChild(wasFeld);
|
|
1208
|
+
li.appendChild(e('span', 'quelle', mcpQuelleText(row)));
|
|
1137
1209
|
if (row.art === 'katalog') {
|
|
1138
|
-
li.appendChild(e('span', 'was', row.beschreibung || ''));
|
|
1139
1210
|
var weg = e('button', 'knopf leise klein', 'Entfernen');
|
|
1140
1211
|
weg.type = 'button';
|
|
1141
1212
|
weg.setAttribute('aria-label', row.name + ' aus ' + zielTitel({ ziel: ziel }) + ' aushängen');
|
|
1142
1213
|
weg.addEventListener('click', function () { frageMcpAus(row.eintrag, ziel); });
|
|
1143
1214
|
li.appendChild(weg);
|
|
1144
1215
|
} else if (row.art === 'geteilt' || row.art === 'fremd-geteilt') {
|
|
1145
|
-
// E64: der Vermerk nennt die Bedeutung („steht im Projekt, nicht bei dir"), nicht mehr bloß
|
|
1146
|
-
// den Dateinamen — und daneben steht der Weg, das zu ändern.
|
|
1147
|
-
li.appendChild(row.art === 'geteilt'
|
|
1148
|
-
? e('span', 'was', row.beschreibung || '')
|
|
1149
|
-
: e('span', 'was fehlt', 'nicht im Katalog'));
|
|
1150
|
-
li.appendChild(e('span', 'geteiltvermerk', 'in der .mcp.json des Projekts'));
|
|
1151
1216
|
var her = e('button', 'knopf leise klein', 'Übernehmen …');
|
|
1152
1217
|
her.type = 'button';
|
|
1153
1218
|
her.setAttribute('aria-label', row.name + ' aus der .mcp.json des Projekts in deine private Konfiguration übernehmen');
|
|
1154
1219
|
her.addEventListener('click', function () { frageMcpUebernahme(row.name, ziel, row.datei); });
|
|
1155
1220
|
li.appendChild(her);
|
|
1156
1221
|
} else {
|
|
1157
|
-
li.appendChild(e('span', 'was fehlt', 'nicht im Katalog'));
|
|
1158
1222
|
li.appendChild(e('span'));
|
|
1159
1223
|
}
|
|
1160
1224
|
ul.appendChild(li);
|
|
1161
1225
|
});
|
|
1162
1226
|
abschnitt.appendChild(ul);
|
|
1227
|
+
notizen.forEach(function (n) { abschnitt.appendChild(e('p', 'ohne mcpkarteleer', n)); });
|
|
1163
1228
|
return abschnitt;
|
|
1164
1229
|
}
|
|
1165
1230
|
|
|
@@ -1357,10 +1422,8 @@
|
|
|
1357
1422
|
if (mcpKnopfLeer) leer.appendChild(mcpKnopfLeer);
|
|
1358
1423
|
});
|
|
1359
1424
|
teil.appendChild(leer);
|
|
1360
|
-
verzMcpZiele
|
|
1361
|
-
|
|
1362
|
-
if (mcpAbschnLeer) teil.appendChild(mcpAbschnLeer);
|
|
1363
|
-
});
|
|
1425
|
+
var mcpAbschnLeer = mcpAbschnitt(verzMcpZiele, teile);
|
|
1426
|
+
if (mcpAbschnLeer) teil.appendChild(mcpAbschnLeer);
|
|
1364
1427
|
return teil;
|
|
1365
1428
|
}
|
|
1366
1429
|
|
|
@@ -1494,10 +1557,8 @@
|
|
|
1494
1557
|
|
|
1495
1558
|
// MCP-Abschnitt (E61-GUI-Nachtrag): auf Kartenebene unter „Alle", wie unter dem Harness-Chip,
|
|
1496
1559
|
// der an diesem Pfad MCP kann.
|
|
1497
|
-
verzMcpZiele
|
|
1498
|
-
|
|
1499
|
-
if (mcpAbschnAlle) teil.appendChild(mcpAbschnAlle);
|
|
1500
|
-
});
|
|
1560
|
+
var mcpAbschnAlle = mcpAbschnitt(verzMcpZiele, teile);
|
|
1561
|
+
if (mcpAbschnAlle) teil.appendChild(mcpAbschnAlle);
|
|
1501
1562
|
|
|
1502
1563
|
var fuss = e('div', 'zielfuss');
|
|
1503
1564
|
fuss.appendChild(alleSkillsKnopf(pfad, teile));
|
|
@@ -771,21 +771,11 @@ dialog::backdrop{background:rgba(9,45,37,.62)}
|
|
|
771
771
|
}
|
|
772
772
|
|
|
773
773
|
/* MCP an der Ziel-Karte (E61-GUI-Nachtrag), Gegenrichtung zur MCP-Ansicht (F46: die einzige Stelle,
|
|
774
|
-
die noch zeigt, wo ein Server hängt): eigener Abschnitt unter der Skill-Link-Tabelle,
|
|
775
|
-
|
|
774
|
+
die noch zeigt, wo ein Server hängt): eigener Abschnitt unter der Skill-Link-Tabelle, seit E120 mit
|
|
775
|
+
derselben Tabelle (linkkopf/linkliste) wie die Skills; flach in der Karte statt in einem eigenen Kasten. */
|
|
776
776
|
.mcpkarteabschnitt{margin-top:16px;padding-top:14px;border-top:1px solid var(--strich)}
|
|
777
777
|
.mcpkarteabschnitt > .etikett{display:block;margin-bottom:10px}
|
|
778
778
|
.mcpkarteleer{margin:0;color:var(--tinte-leise);font-style:italic}
|
|
779
|
-
.mcpkartezeilen{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:10px}
|
|
780
|
-
.mcpkartezeilen li{display:flex;flex-wrap:wrap;align-items:center;gap:5px 14px}
|
|
781
|
-
.mcpkartezeilen .name{font-family:var(--mono);font-size:16px;letter-spacing:-.012em;color:var(--tinte)}
|
|
782
|
-
.mcpkartezeilen .was{font-size:16px;color:var(--tinte-weich)}
|
|
783
|
-
.mcpkartezeilen .was.fehlt{color:var(--tinte-leise);font-style:italic}
|
|
784
|
-
.mcpkartezeilen .knopf{margin-left:auto}
|
|
785
|
-
.mcpkartezeilen .kein-weg{margin-left:auto;font-size:16px;color:var(--tinte-leise);text-align:right}
|
|
786
|
-
/* Wo ein Eintrag steht (E64): kein margin-left:auto, sonst teilte er sich den freien Platz mit dem
|
|
787
|
-
Übernehmen-Knopf und stünde in der Mitte statt beim Text. */
|
|
788
|
-
.mcpkartezeilen .geteiltvermerk{font-size:16px;color:var(--tinte-leise)}
|
|
789
779
|
/* Bundle-Gruppe an der Ziel-Karte (E69, F68): eine Einheit über ihren Skill-Zeilen, sichtbar
|
|
790
780
|
zusammengefasst durch eine linke Kante statt durch einen eigenen Kasten — die Zeilen darin sind
|
|
791
781
|
dieselbe Tabelle wie darunter und sollen mit ihr fluchten. */
|
|
@@ -578,6 +578,15 @@ export class Anwendungsfaelle {
|
|
|
578
578
|
}
|
|
579
579
|
return ziele;
|
|
580
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Die MCP-Ebenen je Harness-Typ (E120), aus der Fähigkeit am Adapter, nie am Namen (E16): eine
|
|
583
|
+
* leere Liste heißt, der Harness kennt MCP-Server gar nicht (agents). Grundlage für die Erklärung,
|
|
584
|
+
* warum ein Server an einem Ort für einen Harness fehlt (GUI-Tooltip, Hinweis von `mcp list`).
|
|
585
|
+
* Unabhängig von Installation und Aktivierung; das entscheidet der Aufrufer.
|
|
586
|
+
*/
|
|
587
|
+
mcpEbenen() {
|
|
588
|
+
return this.p.harnesses.map((h) => ({ harness: h.name, ebenen: kannMcp(h) ? h.mcp.ebenen() : [] }));
|
|
589
|
+
}
|
|
581
590
|
/**
|
|
582
591
|
* Die Plätze für den Einhängen-Dialog der GUI (E61-Folgerunde, F42): dieselbe Liste wie in
|
|
583
592
|
* `mcpUebersicht`, aber roh, ohne den Abgleich mit Katalog-Einträgen. Die Fähigkeit hängt am
|