@cachly-dev/mcp-server 0.10.124 → 0.10.126

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.
Files changed (88) hide show
  1. package/dist/index.d.ts +1 -0
  2. package/dist/index.js +7 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/src/aussetzer.d.ts +67 -0
  5. package/dist/src/aussetzer.js +82 -0
  6. package/dist/src/aussetzer.js.map +1 -0
  7. package/dist/src/autor-abzeichen.d.ts +41 -0
  8. package/dist/src/autor-abzeichen.js +56 -0
  9. package/dist/src/autor-abzeichen.js.map +1 -0
  10. package/dist/src/autor.d.ts +101 -0
  11. package/dist/src/autor.js +136 -0
  12. package/dist/src/autor.js.map +1 -0
  13. package/dist/src/bauabdruck-daten.generiert.json +5 -0
  14. package/dist/src/bauabdruck.d.ts +38 -0
  15. package/dist/src/bauabdruck.js +93 -0
  16. package/dist/src/bauabdruck.js.map +1 -0
  17. package/dist/src/bedeutung.d.ts +175 -0
  18. package/dist/src/bedeutung.js +254 -0
  19. package/dist/src/bedeutung.js.map +1 -0
  20. package/dist/src/brain-export.d.ts +24 -0
  21. package/dist/src/brain-export.js +31 -1
  22. package/dist/src/brain-export.js.map +1 -1
  23. package/dist/src/deutsch.d.ts +98 -0
  24. package/dist/src/deutsch.js +223 -0
  25. package/dist/src/deutsch.js.map +1 -0
  26. package/dist/src/eingaenge-nachruesten.d.ts +41 -0
  27. package/dist/src/eingaenge-nachruesten.js +290 -0
  28. package/dist/src/eingaenge-nachruesten.js.map +1 -0
  29. package/dist/src/eingaenge.d.ts +135 -0
  30. package/dist/src/eingaenge.js +228 -0
  31. package/dist/src/eingaenge.js.map +1 -0
  32. package/dist/src/geliefert.d.ts +63 -0
  33. package/dist/src/geliefert.js +114 -0
  34. package/dist/src/geliefert.js.map +1 -0
  35. package/dist/src/handlers/advanced.js +7 -3
  36. package/dist/src/handlers/advanced.js.map +1 -1
  37. package/dist/src/handlers/brain.d.ts +19 -0
  38. package/dist/src/handlers/brain.js +536 -48
  39. package/dist/src/handlers/brain.js.map +1 -1
  40. package/dist/src/handlers/instances.d.ts +24 -0
  41. package/dist/src/handlers/instances.js +49 -1
  42. package/dist/src/handlers/instances.js.map +1 -1
  43. package/dist/src/handlers/team.js +105 -0
  44. package/dist/src/handlers/team.js.map +1 -1
  45. package/dist/src/index.d.ts +20 -0
  46. package/dist/src/index.js +272 -26
  47. package/dist/src/index.js.map +1 -1
  48. package/dist/src/lesson-preview.d.ts +81 -0
  49. package/dist/src/lesson-preview.js +133 -0
  50. package/dist/src/lesson-preview.js.map +1 -0
  51. package/dist/src/rangfolge.d.ts +169 -0
  52. package/dist/src/rangfolge.js +214 -0
  53. package/dist/src/rangfolge.js.map +1 -0
  54. package/dist/src/raumkorrektur.d.ts +100 -0
  55. package/dist/src/raumkorrektur.js +197 -0
  56. package/dist/src/raumkorrektur.js.map +1 -0
  57. package/dist/src/recall-tiefe.d.ts +48 -0
  58. package/dist/src/recall-tiefe.js +42 -0
  59. package/dist/src/recall-tiefe.js.map +1 -0
  60. package/dist/src/rerank.d.ts +0 -14
  61. package/dist/src/rerank.js +39 -2
  62. package/dist/src/rerank.js.map +1 -1
  63. package/dist/src/search.d.ts +56 -17
  64. package/dist/src/search.js +335 -73
  65. package/dist/src/search.js.map +1 -1
  66. package/dist/src/seltenheitsbestand.d.ts +53 -0
  67. package/dist/src/seltenheitsbestand.js +92 -0
  68. package/dist/src/seltenheitsbestand.js.map +1 -0
  69. package/dist/src/spuren.d.ts +97 -0
  70. package/dist/src/spuren.js +150 -0
  71. package/dist/src/spuren.js.map +1 -0
  72. package/dist/src/tools.js +1 -1
  73. package/dist/src/tools.js.map +1 -1
  74. package/dist/src/versuch.d.ts +179 -0
  75. package/dist/src/versuch.js +250 -0
  76. package/dist/src/versuch.js.map +1 -0
  77. package/dist/src/vorspann.d.ts +73 -0
  78. package/dist/src/vorspann.js +146 -0
  79. package/dist/src/vorspann.js.map +1 -0
  80. package/dist/src/werkzeug-nutzung.d.ts +62 -0
  81. package/dist/src/werkzeug-nutzung.js +72 -0
  82. package/dist/src/werkzeug-nutzung.js.map +1 -0
  83. package/dist/src/wertbeitrag.d.ts +57 -0
  84. package/dist/src/wertbeitrag.js +73 -0
  85. package/dist/src/wertbeitrag.js.map +1 -0
  86. package/glama.json +1 -1
  87. package/package.json +12 -4
  88. package/server.json +2 -2
@@ -4,6 +4,30 @@ type GetConnection = (instanceId: string) => Promise<Redis>;
4
4
  type ApiFetch = <T>(path: string, options?: RequestInit) => Promise<T>;
5
5
  export declare const INSTANCE_TOOL_NAMES: Set<string>;
6
6
  declare function formatInstance(inst: Instance): string;
7
+ /**
8
+ * Baut eine Adresse aus einem Instanz-Datensatz.
9
+ *
10
+ * ── Warum diese Funktion NICHT mehr fuer get_connection_string benutzt wird ──
11
+ *
12
+ * Am 19.08.2026 gemessen: `get_connection_string` gab
13
+ * `redis://49.13.38.27:30114` zurueck — ohne Passwort. Der mitgelieferte
14
+ * "Quick test" (`redis-cli -u ... PING`) scheiterte sofort an NOAUTH. Ein
15
+ * Werkzeug, das eine Verbindungsadresse verspricht und eine liefert, die nicht
16
+ * verbindet.
17
+ *
18
+ * Die Funktion war nicht falsch. Sie bekam nur nie ein Passwort: sie wurde mit
19
+ * dem Datensatz aus /api/v1/instances/:id gefuettert, und der fuehrt kein
20
+ * Passwort — voellig richtig, das ist der allgemeine Instanz-Datensatz. Die
21
+ * Zugangsdaten stehen unter /api/v1/instances/:id/connection, und dort baut der
22
+ * Server die Adresse laengst fertig zusammen.
23
+ *
24
+ * Also gab es zwei Stellen, die wussten, wie eine Adresse aussieht — und nur
25
+ * eine hatte alles, was dazugehoert. Dieselbe Fehlerklasse wie beim Export am
26
+ * selben Tag: eine Frage aus einer Quelle bedient, die fuer eine andere gebaut
27
+ * wurde.
28
+ *
29
+ * Sie bleibt fuer die Anzeige in Listen, wo bewusst kein Passwort hingehoert.
30
+ */
7
31
  declare function buildConnectionString(inst: Instance): string;
8
32
  export declare function handleInstanceTool(name: string, args: Record<string, unknown>, getConnection: GetConnection, apiFetch: ApiFetch): Promise<string | null>;
9
33
  export { formatInstance, buildConnectionString };
@@ -7,6 +7,30 @@ function formatInstance(inst) {
7
7
  const mb = inst.memory_mb >= 1024 ? `${inst.memory_mb / 1024}GB` : `${inst.memory_mb}MB`;
8
8
  return `${badge} **${inst.name}** (\`${inst.id}\`) · ${inst.tier} · ${mb} · ${inst.region}`;
9
9
  }
10
+ /**
11
+ * Baut eine Adresse aus einem Instanz-Datensatz.
12
+ *
13
+ * ── Warum diese Funktion NICHT mehr fuer get_connection_string benutzt wird ──
14
+ *
15
+ * Am 19.08.2026 gemessen: `get_connection_string` gab
16
+ * `redis://49.13.38.27:30114` zurueck — ohne Passwort. Der mitgelieferte
17
+ * "Quick test" (`redis-cli -u ... PING`) scheiterte sofort an NOAUTH. Ein
18
+ * Werkzeug, das eine Verbindungsadresse verspricht und eine liefert, die nicht
19
+ * verbindet.
20
+ *
21
+ * Die Funktion war nicht falsch. Sie bekam nur nie ein Passwort: sie wurde mit
22
+ * dem Datensatz aus /api/v1/instances/:id gefuettert, und der fuehrt kein
23
+ * Passwort — voellig richtig, das ist der allgemeine Instanz-Datensatz. Die
24
+ * Zugangsdaten stehen unter /api/v1/instances/:id/connection, und dort baut der
25
+ * Server die Adresse laengst fertig zusammen.
26
+ *
27
+ * Also gab es zwei Stellen, die wussten, wie eine Adresse aussieht — und nur
28
+ * eine hatte alles, was dazugehoert. Dieselbe Fehlerklasse wie beim Export am
29
+ * selben Tag: eine Frage aus einer Quelle bedient, die fuer eine andere gebaut
30
+ * wurde.
31
+ *
32
+ * Sie bleibt fuer die Anzeige in Listen, wo bewusst kein Passwort hingehoert.
33
+ */
10
34
  function buildConnectionString(inst) {
11
35
  if (!inst.host)
12
36
  return '❌ Instance not ready yet.';
@@ -56,8 +80,32 @@ export async function handleInstanceTool(name, args, getConnection, apiFetch) {
56
80
  if (inst.status !== 'running') {
57
81
  return `Instance is not running yet (status: ${inst.status}). Provisioning takes ~30 seconds after payment.`;
58
82
  }
59
- const connStr = buildConnectionString(inst);
83
+ // Die Adresse kommt vom Server, nicht von hier. Er hat als einziger das
84
+ // Passwort (verschluesselt in der Datenbank, dort entschluesselt) und
85
+ // baut die Zeichenkette bereits vollstaendig zusammen.
86
+ let conn = {};
87
+ let konnteNichtFragen = false;
88
+ try {
89
+ conn = await apiFetch(`/api/v1/instances/${args.instance_id}/connection`);
90
+ }
91
+ catch {
92
+ // Aeltere oder eingeschraenkte Server. Dann bleibt nur der allgemeine
93
+ // Datensatz — der fuehrt kein Passwort. Das ist kein Grund
94
+ // abzubrechen, aber ein Grund, es dazuzuschreiben.
95
+ konnteNichtFragen = true;
96
+ }
97
+ const connStr = conn.connection_string || buildConnectionString(inst);
98
+ // Eine Adresse ohne Passwort ist gegen ein passwortgeschuetztes Valkey
99
+ // nutzlos — sie scheitert mit NOAUTH, und zwar erst beim Nutzer. Deshalb
100
+ // steht der Hinweis hier, ueber der Adresse, nicht in einer Fussnote.
101
+ const ohnePasswort = !connStr.includes('@');
102
+ const warnung = !ohnePasswort ? [] : konnteNichtFragen
103
+ ? ['⚠️ Could not read the credentials endpoint — this string has NO password and will fail with NOAUTH if the instance requires one.', '']
104
+ : conn.password
105
+ ? ['⚠️ The server returned a password but this string carries none — please report this.', '']
106
+ : [];
60
107
  return [
108
+ ...warnung,
61
109
  `**Connection string for ${inst.name}:**`,
62
110
  `\`\`\``,
63
111
  connStr,
@@ -1 +1 @@
1
- {"version":3,"file":"instances.js","sourceRoot":"","sources":["../../../src/handlers/instances.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"instances.js","sourceRoot":"","sources":["../../../src/handlers/instances.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,10 @@
1
1
  import { readFileSync } from 'node:fs';
2
+ import { bauabdruck, formatiereBauabdruck } from '../bauabdruck.js';
3
+ import { beurteileDeckung } from '../eingaenge.js';
2
4
  import { join } from 'node:path';
3
5
  import { calculateConfidence, CONFIDENCE_STALE_VALUE, CONFIDENCE_WARN_VALUE, CONFIDENCE_WARN_DAYS, CONFIDENCE_STALE_DAYS } from '../confidence.js';
4
6
  import { safeJsonParse } from '../utils.js';
7
+ import { ersparteMinuten, istStarterLektion, fmtStunden } from '../wertbeitrag.js';
5
8
  import { cachlyUrl } from '../cachly-url.js';
6
9
  export const TEAM_TOOL_NAMES = new Set([
7
10
  'sync_file_changes', 'team_learn', 'team_confirm', 'team_recall', 'team_synthesize', 'memory_crystalize', 'team_crystallize',
@@ -667,6 +670,60 @@ export async function handleTeamTool(name, args, getConnection, apiFetch) {
667
670
  // Effective IQ boost: total recalls / lessons (how much the brain actually helped)
668
671
  const totalRecalls = lessons.reduce((sum, l) => sum + (l.recall_count ?? 0), 0);
669
672
  const iqBoostPct = lessons.length > 0 ? Math.min(100, Math.round((totalRecalls / lessons.length) * 10)) : 0;
673
+ // ── Deckung des Bedeutungsabgleichs ─────────────────────────────────
674
+ //
675
+ // Gemessen am 20.08.2026 gegen die Produktion: `cachly:lesson:vec:*` war
676
+ // LEER — 0 Vektoren bei 506 Lektionen. Damit lief der Bedeutungsabgleich
677
+ // dort nie: `brain.ts` steigt bei `vektorbestand.groesse === 0` aus und
678
+ // faellt auf den reinen Wortabgleich zurueck.
679
+ //
680
+ // Von aussen war dieser Zustand von "alles in Ordnung" nicht zu
681
+ // unterscheiden — die Suche lieferte weiter Ergebnisse, nur schlechtere.
682
+ // Genau das ist die Fehlerklasse "Stille wird als gruen gebucht": es gab
683
+ // eine Zahl fuer alles Moegliche, aber keine fuer DAS.
684
+ const zaehleSchluessel = async (muster) => {
685
+ let n = 0;
686
+ const st = redis.scanStream({ match: muster, count: 200 });
687
+ await new Promise((resolve, reject) => {
688
+ st.on('data', (batch) => { n += batch.length; });
689
+ st.on('end', resolve);
690
+ st.on('error', reject);
691
+ });
692
+ return n;
693
+ };
694
+ const vektorZahl = await zaehleSchluessel('cachly:lesson:vec:*');
695
+ const namensZahl = await zaehleSchluessel('cachly:lesson:vecname:*');
696
+ const eingangZahl = await zaehleSchluessel('cachly:lesson:eing:*');
697
+ const pfadZahl = await zaehleSchluessel('cachly:lesson:pfad:*');
698
+ const deckung = lessonKeys.length > 0
699
+ ? Math.round((vektorZahl / lessonKeys.length) * 100)
700
+ : 100;
701
+ const urteil = beurteileDeckung(lessonKeys.length, vektorZahl);
702
+ if (lessonKeys.length > 0) {
703
+ if (urteil === 'aus') {
704
+ issues.push('semantic search is OFF: not a single lesson has an embedding '
705
+ + `(0 of ${lessonKeys.length}). Recall falls back to keyword matching only. `
706
+ + 'Fix: run the backfill (sdk/mcp/src/eingaenge-nachruesten.ts).');
707
+ checks.push(`🔴 **Semantic search: OFF** — 0 of ${lessonKeys.length} lessons have an embedding`);
708
+ }
709
+ else if (urteil === 'luecke') {
710
+ issues.push(`only ${deckung}% of lessons have an embedding (${vektorZahl} of ${lessonKeys.length}) — `
711
+ + 'the rest can never be found by meaning.');
712
+ checks.push(`🟡 **Semantic coverage: ${deckung}%** — ${lessonKeys.length - vektorZahl} lessons without an embedding`);
713
+ }
714
+ else {
715
+ checks.push(`✅ **Semantic coverage: ${deckung}%** — ${vektorZahl} full-text, `
716
+ + `${namensZahl} topic-name, ${eingangZahl} with error-text entries`
717
+ + (pfadZahl > 0 ? `, ${pfadZahl} with learned question paths` : ''));
718
+ // Die Trampelpfade sind das einzige, was MIT DER NUTZUNG waechst.
719
+ // Steht die Zahl auf null, obwohl schon lange gesucht wird, lernt
720
+ // das Gedaechtnis nichts dazu — das ist eine eigene Auskunft.
721
+ if (pfadZahl === 0 && lessonKeys.length >= 20) {
722
+ checks.push('💤 **No learned question paths yet** — a question that finds the same '
723
+ + 'lesson twice becomes its own entry. Needs repeated real use.');
724
+ }
725
+ }
726
+ }
670
727
  // Quality score (0-100)
671
728
  let score = 50;
672
729
  if (lessonKeys.length >= 5)
@@ -688,6 +745,11 @@ export async function handleTeamTool(name, args, getConnection, apiFetch) {
688
745
  score += 5;
689
746
  if (uniqueAuthors.size >= 2)
690
747
  score += 5; // team collaboration bonus
748
+ // Ohne Einbettungen laeuft die halbe Suche nicht — das darf keine
749
+ // Randnotiz sein, sondern muss die Zahl druecken, die oben steht.
750
+ if (urteil !== 'gut')
751
+ score -= 20;
752
+ score = Math.max(0, Math.min(100, score));
691
753
  const scoreEmoji = score >= 80 ? '🟢' : score >= 50 ? '🟡' : '🔴';
692
754
  const iqEmoji = iqBoostPct >= 50 ? '🚀' : iqBoostPct >= 20 ? '📈' : '💤';
693
755
  checks.push(`${scoreEmoji} **Brain Quality Score: ${score}/100**`);
@@ -696,6 +758,7 @@ export async function handleTeamTool(name, args, getConnection, apiFetch) {
696
758
  checks.push(`💾 **Context entries:** ${ctxCount}`);
697
759
  checks.push(`🎯 **Confidence:** ${lessons.length - staleLessons.length - warnLessons.length} fresh · ${warnLessons.length} warn · ${staleLessons.length} stale`);
698
760
  checks.push(`⏱️ **Decay config:** warn after ${CONFIDENCE_WARN_DAYS}d · stale after ${CONFIDENCE_STALE_DAYS}d`);
761
+ checks.push(formatiereBauabdruck(bauabdruck));
699
762
  if (uniqueAuthors.size >= 2) {
700
763
  checks.push(`👥 **Team:** ${uniqueAuthors.size} contributors (${[...uniqueAuthors].join(', ')})`);
701
764
  }
@@ -932,6 +995,42 @@ export async function handleTeamTool(name, args, getConnection, apiFetch) {
932
995
  updates.set(lesson._key, updated);
933
996
  }
934
997
  }
998
+ // ── Regel 4: Startvorrat entwerten und Zeitersparnis neu rechnen ──────
999
+ //
1000
+ // ANLASS (17.08.2026): Ein Brain mit 475 Lektionen zeigte 54 Tage
1001
+ // eingesparte Entwicklerzeit und 97.237,50 € Gegenwert. Nachgerechnet kam
1002
+ // praktisch alles aus dem mitgelieferten Startvorrat — `docker:layer-cache`
1003
+ // bei 973 Abrufen, `cache:stampede` bei 971, dahinter neun weitere bei je
1004
+ // rund 208. Die echten Lektionen standen bei zwei bis fünf.
1005
+ //
1006
+ // Ab jetzt zählen Starter-Abrufe nicht mehr mit (wertbeitrag.ts). Das
1007
+ // stoppt aber nur das Weiterwachsen; die aufgelaufenen Zähler bleiben und
1008
+ // tragen die Zahl weiter. Deshalb hier zweierlei:
1009
+ //
1010
+ // 1. Starter-Zähler auf 0. Sie sind keine Leistung dieses Teams.
1011
+ // 2. time_saved_mins NEU BERECHNEN statt zu korrigieren. Die alte Summe
1012
+ // ist nicht rekonstruierbar (sie wurde im Juli schon einmal
1013
+ // zurückgesetzt und geht nicht mit der Summe der Einzelzähler auf).
1014
+ // Etwas davon abzuziehen ergäbe eine Zahl, die genauso erfunden wäre
1015
+ // wie die alte — nur unauffälliger. Neu gerechnet ist sie prüfbar:
1016
+ // Summe über alle NICHT-Starter-Lektionen aus Abrufzahl mal Staffel.
1017
+ let starterZurueckgesetzt = 0;
1018
+ let minutenNeu = 0;
1019
+ const minutenAlt = parseFloat((await redis.get(`cachly:stats:time_saved_mins:${instance_id}`)) ?? '0') || 0;
1020
+ for (const lesson of lessons) {
1021
+ if (istStarterLektion(lesson)) {
1022
+ if ((lesson.recall_count ?? 0) > 0) {
1023
+ starterZurueckgesetzt++;
1024
+ const bisher = updates.get(lesson._key) ?? lesson;
1025
+ updates.set(lesson._key, { ...bisher, recall_count: 0 });
1026
+ }
1027
+ continue;
1028
+ }
1029
+ minutenNeu += (lesson.recall_count ?? 0) * ersparteMinuten(lesson);
1030
+ }
1031
+ if (!dry_run) {
1032
+ await redis.set(`cachly:stats:time_saved_mins:${instance_id}`, String(minutenNeu)).catch(() => { });
1033
+ }
935
1034
  // ── Flush updates ─────────────────────────────────────────────────────
936
1035
  if (!dry_run && updates.size > 0) {
937
1036
  const pipeline = redis.pipeline();
@@ -952,8 +1051,14 @@ export async function handleTeamTool(name, args, getConnection, apiFetch) {
952
1051
  `| Flagged provisional (confidence < ${provisional_threshold}) | ${provisionalKeys.length} |`,
953
1052
  `| Archived (stale + low-recall + age > ${archive_days}d) | ${archivedKeys.length} |`,
954
1053
  `| Contradictions auto-resolved | ${conflictResolutions.length} |`,
1054
+ `| Startvorrat entwertet (Zähler auf 0) | ${starterZurueckgesetzt} |`,
955
1055
  '',
956
1056
  ];
1057
+ if (Math.round(minutenAlt) !== Math.round(minutenNeu)) {
1058
+ // Die Zahl beim Namen nennen, nicht nur still korrigieren. Wer morgen
1059
+ // eine kleinere Ersparnis im Panel sieht, soll hier lesen koennen warum.
1060
+ lines.push(`**⏱️ Zeitersparnis neu gerechnet:** ${fmtStunden(minutenAlt)} → **${fmtStunden(minutenNeu)}**`, `_Nur noch eigene Lektionen. Der mitgelieferte Startvorrat zählt nicht mehr — er ist Allgemeinwissen, kein gelerntes._`, '');
1061
+ }
957
1062
  if (provisionalKeys.length > 0) {
958
1063
  lines.push(`**⚠️ Provisional (verify or re-learn):**`);
959
1064
  provisionalKeys.slice(0, 10).forEach(t => lines.push(` - \`${t}\``));