@cachly-dev/mcp-server 0.10.129 → 0.10.131
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/README.md +2 -2
- package/dist/index.js +1 -7
- package/dist/packages/telegram-notify/client.js +2 -75
- package/dist/src/ambient-cli.js +7 -253
- package/dist/src/ambient-deps.js +1 -55
- package/dist/src/ambient-hooks.js +5 -278
- package/dist/src/ambient-ledger.js +6 -95
- package/dist/src/ambient-memory.js +1 -67
- package/dist/src/ambient-recall.js +1 -221
- package/dist/src/aussetzer.js +1 -225
- package/dist/src/auth.js +9 -140
- package/dist/src/autor-abzeichen.js +1 -56
- package/dist/src/autor.js +1 -136
- package/dist/src/bauabdruck.js +1 -93
- package/dist/src/bedeutung.js +2 -323
- package/dist/src/bench/cachly-bench.js +4 -249
- package/dist/src/bench/external-corpus.js +4 -135
- package/dist/src/bench/fixtures.js +1 -225
- package/dist/src/brain-export.js +16 -119
- package/dist/src/brain-watch-hook.js +8 -86
- package/dist/src/cachly-url.js +1 -21
- package/dist/src/ckg.js +1 -108
- package/dist/src/cls-hook.js +8 -94
- package/dist/src/confidence.js +1 -50
- package/dist/src/credentials.js +1 -85
- package/dist/src/deutsch.js +1 -223
- package/dist/src/doctor.js +2 -248
- package/dist/src/editor.js +1 -63
- package/dist/src/eingaenge-nachruesten.js +1 -290
- package/dist/src/eingaenge.js +2 -260
- package/dist/src/embeddings.js +13 -223
- package/dist/src/feldreparatur.js +3 -113
- package/dist/src/first-contact.js +4 -108
- package/dist/src/first-recall-proof.js +4 -41
- package/dist/src/funnel-milestones.js +2 -48
- package/dist/src/geliefert.js +1 -114
- package/dist/src/handlers/advanced.js +38 -537
- package/dist/src/handlers/brain.js +69 -4397
- package/dist/src/handlers/cache.js +59 -638
- package/dist/src/handlers/context.js +17 -182
- package/dist/src/handlers/fedbrain.js +40 -1436
- package/dist/src/handlers/instances.js +16 -201
- package/dist/src/handlers/roadmap.js +13 -175
- package/dist/src/handlers/share.js +19 -530
- package/dist/src/handlers/syndicate.js +38 -904
- package/dist/src/handlers/team.js +89 -1865
- package/dist/src/handlers/viz.js +3 -148
- package/dist/src/index.js +321 -4281
- package/dist/src/interferenz.js +1 -141
- package/dist/src/kostprobe.js +7 -125
- package/dist/src/lesson-preview.js +2 -133
- package/dist/src/namespace.js +1 -128
- package/dist/src/notifier.js +1 -6
- package/dist/src/rangfolge-stellschrauben.js +1 -0
- package/dist/src/rangfolge.js +1 -249
- package/dist/src/raumkorrektur.js +1 -197
- package/dist/src/recall-tiefe.js +1 -42
- package/dist/src/rerank.js +1 -154
- package/dist/src/resonanz.js +1 -140
- package/dist/src/search.js +1 -2104
- package/dist/src/seltenheitsbestand.js +1 -92
- package/dist/src/speicherlage.js +1 -84
- package/dist/src/spuren.js +1 -150
- package/dist/src/starter-corpus.js +1 -165
- package/dist/src/telemetry-types.js +0 -13
- package/dist/src/tools.js +10 -2465
- package/dist/src/toolspecs.js +1 -121
- package/dist/src/upgrade-nudge.js +1 -29
- package/dist/src/utils.js +1 -89
- package/dist/src/versuch.js +1 -264
- package/dist/src/vorspann.js +1 -146
- package/dist/src/wartung/vektoren-verdichten.js +1 -200
- package/dist/src/werkzeug-nutzung.js +1 -72
- package/dist/src/wertbeitrag.js +1 -203
- package/dist/src/wirkungsspur.js +1 -0
- package/glama.json +1 -1
- package/package.json +8 -7
- package/server.json +3 -3
- package/dist/index.d.ts +0 -1
- package/dist/index.js.map +0 -1
- package/dist/packages/telegram-notify/client.d.ts +0 -19
- package/dist/packages/telegram-notify/client.js.map +0 -1
- package/dist/src/ambient-cli.d.ts +0 -101
- package/dist/src/ambient-cli.js.map +0 -1
- package/dist/src/ambient-deps.d.ts +0 -26
- package/dist/src/ambient-deps.js.map +0 -1
- package/dist/src/ambient-hooks.d.ts +0 -137
- package/dist/src/ambient-hooks.js.map +0 -1
- package/dist/src/ambient-ledger.d.ts +0 -19
- package/dist/src/ambient-ledger.js.map +0 -1
- package/dist/src/ambient-memory.d.ts +0 -12
- package/dist/src/ambient-memory.js.map +0 -1
- package/dist/src/ambient-recall.d.ts +0 -127
- package/dist/src/ambient-recall.js.map +0 -1
- package/dist/src/aussetzer.d.ts +0 -156
- package/dist/src/aussetzer.js.map +0 -1
- package/dist/src/auth.d.ts +0 -43
- package/dist/src/auth.js.map +0 -1
- package/dist/src/autor-abzeichen.d.ts +0 -41
- package/dist/src/autor-abzeichen.js.map +0 -1
- package/dist/src/autor.d.ts +0 -101
- package/dist/src/autor.js.map +0 -1
- package/dist/src/bauabdruck-daten.generiert.json +0 -5
- package/dist/src/bauabdruck.d.ts +0 -38
- package/dist/src/bauabdruck.js.map +0 -1
- package/dist/src/bedeutung.d.ts +0 -168
- package/dist/src/bedeutung.js.map +0 -1
- package/dist/src/bench/cachly-bench.d.ts +0 -61
- package/dist/src/bench/cachly-bench.js.map +0 -1
- package/dist/src/bench/external-corpus.d.ts +0 -44
- package/dist/src/bench/external-corpus.js.map +0 -1
- package/dist/src/bench/fixtures.d.ts +0 -37
- package/dist/src/bench/fixtures.js.map +0 -1
- package/dist/src/brain-export.d.ts +0 -64
- package/dist/src/brain-export.js.map +0 -1
- package/dist/src/brain-watch-hook.d.ts +0 -21
- package/dist/src/brain-watch-hook.js.map +0 -1
- package/dist/src/cachly-url.d.ts +0 -68
- package/dist/src/cachly-url.js.map +0 -1
- package/dist/src/ckg.d.ts +0 -54
- package/dist/src/ckg.js.map +0 -1
- package/dist/src/cls-hook.d.ts +0 -15
- package/dist/src/cls-hook.js.map +0 -1
- package/dist/src/confidence.d.ts +0 -19
- package/dist/src/confidence.js.map +0 -1
- package/dist/src/credentials.d.ts +0 -37
- package/dist/src/credentials.js.map +0 -1
- package/dist/src/deutsch.d.ts +0 -98
- package/dist/src/deutsch.js.map +0 -1
- package/dist/src/doctor.d.ts +0 -47
- package/dist/src/doctor.js.map +0 -1
- package/dist/src/editor.d.ts +0 -9
- package/dist/src/editor.js.map +0 -1
- package/dist/src/eingaenge-nachruesten.d.ts +0 -41
- package/dist/src/eingaenge-nachruesten.js.map +0 -1
- package/dist/src/eingaenge.d.ts +0 -159
- package/dist/src/eingaenge.js.map +0 -1
- package/dist/src/embeddings.d.ts +0 -48
- package/dist/src/embeddings.js.map +0 -1
- package/dist/src/feldreparatur.d.ts +0 -58
- package/dist/src/feldreparatur.js.map +0 -1
- package/dist/src/first-contact.d.ts +0 -56
- package/dist/src/first-contact.js.map +0 -1
- package/dist/src/first-recall-proof.d.ts +0 -19
- package/dist/src/first-recall-proof.js.map +0 -1
- package/dist/src/funnel-milestones.d.ts +0 -5
- package/dist/src/funnel-milestones.js.map +0 -1
- package/dist/src/geliefert.d.ts +0 -63
- package/dist/src/geliefert.js.map +0 -1
- package/dist/src/handlers/advanced.d.ts +0 -6
- package/dist/src/handlers/advanced.js.map +0 -1
- package/dist/src/handlers/brain.d.ts +0 -41
- package/dist/src/handlers/brain.js.map +0 -1
- package/dist/src/handlers/cache.d.ts +0 -6
- package/dist/src/handlers/cache.js.map +0 -1
- package/dist/src/handlers/context.d.ts +0 -6
- package/dist/src/handlers/context.js.map +0 -1
- package/dist/src/handlers/fedbrain.d.ts +0 -18
- package/dist/src/handlers/fedbrain.js.map +0 -1
- package/dist/src/handlers/instances.d.ts +0 -33
- package/dist/src/handlers/instances.js.map +0 -1
- package/dist/src/handlers/roadmap.d.ts +0 -6
- package/dist/src/handlers/roadmap.js.map +0 -1
- package/dist/src/handlers/share.d.ts +0 -8
- package/dist/src/handlers/share.js.map +0 -1
- package/dist/src/handlers/syndicate.d.ts +0 -6
- package/dist/src/handlers/syndicate.js.map +0 -1
- package/dist/src/handlers/team.d.ts +0 -45
- package/dist/src/handlers/team.js.map +0 -1
- package/dist/src/handlers/viz.d.ts +0 -6
- package/dist/src/handlers/viz.js.map +0 -1
- package/dist/src/index.d.ts +0 -93
- package/dist/src/index.js.map +0 -1
- package/dist/src/interferenz.d.ts +0 -111
- package/dist/src/interferenz.js.map +0 -1
- package/dist/src/kostprobe.d.ts +0 -25
- package/dist/src/kostprobe.js.map +0 -1
- package/dist/src/lesson-preview.d.ts +0 -81
- package/dist/src/lesson-preview.js.map +0 -1
- package/dist/src/namespace.d.ts +0 -20
- package/dist/src/namespace.js.map +0 -1
- package/dist/src/notifier.d.ts +0 -5
- package/dist/src/notifier.js.map +0 -1
- package/dist/src/rangfolge.d.ts +0 -205
- package/dist/src/rangfolge.js.map +0 -1
- package/dist/src/raumkorrektur.d.ts +0 -100
- package/dist/src/raumkorrektur.js.map +0 -1
- package/dist/src/recall-tiefe.d.ts +0 -48
- package/dist/src/recall-tiefe.js.map +0 -1
- package/dist/src/rerank.d.ts +0 -48
- package/dist/src/rerank.js.map +0 -1
- package/dist/src/resonanz.d.ts +0 -85
- package/dist/src/resonanz.js.map +0 -1
- package/dist/src/search.d.ts +0 -153
- package/dist/src/search.js.map +0 -1
- package/dist/src/seltenheitsbestand.d.ts +0 -53
- package/dist/src/seltenheitsbestand.js.map +0 -1
- package/dist/src/speicherlage.d.ts +0 -51
- package/dist/src/speicherlage.js.map +0 -1
- package/dist/src/spuren.d.ts +0 -97
- package/dist/src/spuren.js.map +0 -1
- package/dist/src/starter-corpus.d.ts +0 -28
- package/dist/src/starter-corpus.js.map +0 -1
- package/dist/src/telemetry-types.d.ts +0 -87
- package/dist/src/telemetry-types.js.map +0 -1
- package/dist/src/tools.d.ts +0 -2933
- package/dist/src/tools.js.map +0 -1
- package/dist/src/toolspecs.d.ts +0 -43
- package/dist/src/toolspecs.js.map +0 -1
- package/dist/src/upgrade-nudge.d.ts +0 -15
- package/dist/src/upgrade-nudge.js.map +0 -1
- package/dist/src/utils.d.ts +0 -34
- package/dist/src/utils.js.map +0 -1
- package/dist/src/versuch.d.ts +0 -187
- package/dist/src/versuch.js.map +0 -1
- package/dist/src/vorspann.d.ts +0 -73
- package/dist/src/vorspann.js.map +0 -1
- package/dist/src/wartung/vektoren-verdichten.d.ts +0 -50
- package/dist/src/wartung/vektoren-verdichten.js.map +0 -1
- package/dist/src/werkzeug-nutzung.d.ts +0 -62
- package/dist/src/werkzeug-nutzung.js.map +0 -1
- package/dist/src/wertbeitrag.d.ts +0 -148
- package/dist/src/wertbeitrag.js.map +0 -1
|
@@ -1,200 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Vektoren von float32 auf int8 umschreiben — der Umzug, den `packe` braucht.
|
|
3
|
-
*
|
|
4
|
-
* ── Warum es das gibt ───────────────────────────────────────────────────────
|
|
5
|
-
*
|
|
6
|
-
* Am 20.08.2026 belegte ein Bestand mit 524 Lektionen 23,6 MB von 25 MB
|
|
7
|
-
* Tarifgrenze — 94 %. Davon waren 11,2 MB Vektoren: 6,0 MB Volltext und Namen,
|
|
8
|
-
* 5,2 MB Eingänge. Die nächste Lektion wäre an einem Schreibfehler gescheitert.
|
|
9
|
-
*
|
|
10
|
-
* `packe` schreibt seither int8 statt float32 (Faktor 3,96). Neu geschriebene
|
|
11
|
-
* Lektionen sind damit klein. Die BESTEHENDEN bleiben groß, bis sie einmal neu
|
|
12
|
-
* gelernt werden — und die meisten werden nie neu gelernt. Dieses Werkzeug
|
|
13
|
-
* holt sie ein.
|
|
14
|
-
*
|
|
15
|
-
* ── Was es tut, und in welcher Reihenfolge ─────────────────────────────────
|
|
16
|
-
*
|
|
17
|
-
* 1. Sichern: jeder betroffene Schlüssel wird VORHER in eine Datei geschrieben.
|
|
18
|
-
* 2. Prüfen: die Sicherung wird zurückgelesen und muss vollständig sein.
|
|
19
|
-
* 3. Umschreiben: erst danach wird der Speicher angefasst.
|
|
20
|
-
*
|
|
21
|
-
* Ohne Schritt 2 wäre die Sicherung eine Behauptung. Eine Sicherung, die nie
|
|
22
|
-
* zurückgelesen wurde, ist keine.
|
|
23
|
-
*
|
|
24
|
-
* Aufruf:
|
|
25
|
-
* REDIS_URL=... npx tsx src/wartung/vektoren-verdichten.ts --sicherung <datei>
|
|
26
|
-
* REDIS_URL=... npx tsx src/wartung/vektoren-verdichten.ts --sicherung <datei> --schreiben
|
|
27
|
-
* REDIS_URL=... npx tsx src/wartung/vektoren-verdichten.ts --sicherung <datei> --zurueck
|
|
28
|
-
*
|
|
29
|
-
* Ohne `--schreiben` wird nur gerechnet und gemeldet. Das ist Absicht: der
|
|
30
|
-
* Trockenlauf ist der Normalfall, das Schreiben ist der Sonderfall.
|
|
31
|
-
*/
|
|
32
|
-
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
|
33
|
-
import { Redis } from 'ioredis';
|
|
34
|
-
import { packe, entpacke } from '../bedeutung.js';
|
|
35
|
-
/** Alle Schlüssel zu einem Muster, ohne KEYS (das blockiert den Server). */
|
|
36
|
-
export async function alleSchluessel(redis, muster) {
|
|
37
|
-
const aus = [];
|
|
38
|
-
let cursor = '0';
|
|
39
|
-
do {
|
|
40
|
-
const [next, gefunden] = await redis.scan(cursor, 'MATCH', muster, 'COUNT', 500);
|
|
41
|
-
cursor = next;
|
|
42
|
-
aus.push(...gefunden);
|
|
43
|
-
} while (cursor !== '0');
|
|
44
|
-
return aus;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Ist dieser Wert schon im neuen Format?
|
|
48
|
-
*
|
|
49
|
-
* Wird gebraucht, damit ein zweiter Lauf nichts kaputt macht und nichts doppelt
|
|
50
|
-
* zählt. Ein Umzug, der nur einmal laufen darf, ist ein Umzug mit einer Falle.
|
|
51
|
-
*/
|
|
52
|
-
export function istInt8(base64) {
|
|
53
|
-
const b = Buffer.from(base64, 'base64');
|
|
54
|
-
return b.byteLength > 7 && b[0] === 0x01 && b.byteLength % 4 === 1;
|
|
55
|
-
}
|
|
56
|
-
/** Rechnet aus, was der Umzug bringt — und schreibt nur, wenn `schreiben` gesetzt ist. */
|
|
57
|
-
export async function verdichte(redis, schreiben) {
|
|
58
|
-
const b = { schluessel: 0, felder: 0, vorher: 0, nachher: 0, uebersprungen: 0 };
|
|
59
|
-
// Einfache Werte: Volltext- und Namensvektoren.
|
|
60
|
-
for (const muster of ['cachly:lesson:vec:*', 'cachly:lesson:vecname:*']) {
|
|
61
|
-
for (const k of await alleSchluessel(redis, muster)) {
|
|
62
|
-
const roh = await redis.get(k);
|
|
63
|
-
if (!roh)
|
|
64
|
-
continue;
|
|
65
|
-
b.schluessel++;
|
|
66
|
-
if (istInt8(roh)) {
|
|
67
|
-
b.uebersprungen++;
|
|
68
|
-
b.vorher += roh.length;
|
|
69
|
-
b.nachher += roh.length;
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const v = entpacke(roh);
|
|
73
|
-
if (!v) {
|
|
74
|
-
b.uebersprungen++;
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
const neu = packe(v);
|
|
78
|
-
b.vorher += roh.length;
|
|
79
|
-
b.nachher += neu.length;
|
|
80
|
-
b.felder++;
|
|
81
|
-
if (schreiben)
|
|
82
|
-
await redis.set(k, neu);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
// Eingänge: ein Hash je Lektion, ein Vektor je Feld.
|
|
86
|
-
for (const k of await alleSchluessel(redis, 'cachly:lesson:eing:*')) {
|
|
87
|
-
const h = await redis.hgetall(k);
|
|
88
|
-
const felder = [];
|
|
89
|
-
b.schluessel++;
|
|
90
|
-
for (const [feld, roh] of Object.entries(h)) {
|
|
91
|
-
if (istInt8(roh)) {
|
|
92
|
-
b.uebersprungen++;
|
|
93
|
-
b.vorher += roh.length;
|
|
94
|
-
b.nachher += roh.length;
|
|
95
|
-
continue;
|
|
96
|
-
}
|
|
97
|
-
const v = entpacke(roh);
|
|
98
|
-
if (!v) {
|
|
99
|
-
b.uebersprungen++;
|
|
100
|
-
continue;
|
|
101
|
-
}
|
|
102
|
-
const neu = packe(v);
|
|
103
|
-
b.vorher += roh.length;
|
|
104
|
-
b.nachher += neu.length;
|
|
105
|
-
b.felder++;
|
|
106
|
-
felder.push(feld, neu);
|
|
107
|
-
}
|
|
108
|
-
if (schreiben && felder.length > 0)
|
|
109
|
-
await redis.hset(k, ...felder);
|
|
110
|
-
}
|
|
111
|
-
return b;
|
|
112
|
-
}
|
|
113
|
-
const mb = (zeichen) => `${(zeichen / 1024 / 1024).toFixed(2)} MB`;
|
|
114
|
-
async function main() {
|
|
115
|
-
const argv = process.argv.slice(2);
|
|
116
|
-
const flag = (n) => {
|
|
117
|
-
const i = argv.indexOf(`--${n}`);
|
|
118
|
-
return i !== -1 ? argv[i + 1] : undefined;
|
|
119
|
-
};
|
|
120
|
-
const url = process.env.CACHLY_REDIS_URL ?? process.env.REDIS_URL;
|
|
121
|
-
if (!url) {
|
|
122
|
-
console.error('NICHT GELAUFEN: REDIS_URL fehlt.');
|
|
123
|
-
process.exit(2);
|
|
124
|
-
}
|
|
125
|
-
const sicherungsPfad = flag('sicherung');
|
|
126
|
-
if (!sicherungsPfad) {
|
|
127
|
-
console.error('NICHT GELAUFEN: --sicherung <datei> fehlt.');
|
|
128
|
-
process.exit(2);
|
|
129
|
-
}
|
|
130
|
-
const schreiben = argv.includes('--schreiben');
|
|
131
|
-
const zurueck = argv.includes('--zurueck');
|
|
132
|
-
const redis = new Redis(url, { maxRetriesPerRequest: 2, connectTimeout: 8000 });
|
|
133
|
-
try {
|
|
134
|
-
if (zurueck) {
|
|
135
|
-
if (!existsSync(sicherungsPfad)) {
|
|
136
|
-
console.error(`NICHT GELAUFEN: Sicherung fehlt (${sicherungsPfad}).`);
|
|
137
|
-
process.exit(2);
|
|
138
|
-
}
|
|
139
|
-
const s = JSON.parse(readFileSync(sicherungsPfad, 'utf8'));
|
|
140
|
-
let n = 0;
|
|
141
|
-
for (const [k, v] of Object.entries(s.werte)) {
|
|
142
|
-
await redis.set(k, v);
|
|
143
|
-
n++;
|
|
144
|
-
}
|
|
145
|
-
for (const [k, h] of Object.entries(s.hashes)) {
|
|
146
|
-
const felder = Object.entries(h).flat();
|
|
147
|
-
if (felder.length === 0)
|
|
148
|
-
continue;
|
|
149
|
-
await redis.del(k);
|
|
150
|
-
await redis.hset(k, ...felder);
|
|
151
|
-
n++;
|
|
152
|
-
}
|
|
153
|
-
console.log(`ZURUECKGESPIELT: ${n} Schluessel aus ${sicherungsPfad}`);
|
|
154
|
-
return;
|
|
155
|
-
}
|
|
156
|
-
// 1. Sichern — immer, auch im Trockenlauf.
|
|
157
|
-
const werte = {};
|
|
158
|
-
const hashes = {};
|
|
159
|
-
for (const muster of ['cachly:lesson:vec:*', 'cachly:lesson:vecname:*']) {
|
|
160
|
-
for (const k of await alleSchluessel(redis, muster)) {
|
|
161
|
-
const roh = await redis.get(k);
|
|
162
|
-
if (roh)
|
|
163
|
-
werte[k] = roh;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
for (const k of await alleSchluessel(redis, 'cachly:lesson:eing:*')) {
|
|
167
|
-
hashes[k] = await redis.hgetall(k);
|
|
168
|
-
}
|
|
169
|
-
writeFileSync(sicherungsPfad, JSON.stringify({ werte, hashes }), { encoding: 'utf8' });
|
|
170
|
-
// 2. Sicherung zurueckLESEN und pruefen. Ungeprueft ist sie keine.
|
|
171
|
-
const probe = JSON.parse(readFileSync(sicherungsPfad, 'utf8'));
|
|
172
|
-
const wSoll = Object.keys(werte).length;
|
|
173
|
-
const wIst = Object.keys(probe.werte).length;
|
|
174
|
-
const hSoll = Object.keys(hashes).length;
|
|
175
|
-
const hIst = Object.keys(probe.hashes).length;
|
|
176
|
-
if (wSoll !== wIst || hSoll !== hIst || wSoll === 0) {
|
|
177
|
-
console.error(`ABBRUCH: Sicherung unvollstaendig (${wIst}/${wSoll} Werte, ${hIst}/${hSoll} Hashes).`);
|
|
178
|
-
process.exit(3);
|
|
179
|
-
}
|
|
180
|
-
console.log(`Sicherung geprueft: ${wIst} Werte + ${hIst} Hashes in ${sicherungsPfad}`);
|
|
181
|
-
// 3. Erst jetzt rechnen bzw. schreiben.
|
|
182
|
-
const b = await verdichte(redis, schreiben);
|
|
183
|
-
console.log('');
|
|
184
|
-
console.log(` Schluessel angesehen : ${b.schluessel}`);
|
|
185
|
-
console.log(` Vektoren umgeschrieben: ${b.felder}`);
|
|
186
|
-
console.log(` uebersprungen : ${b.uebersprungen} (schon int8 oder unlesbar)`);
|
|
187
|
-
console.log(` vorher : ${mb(b.vorher)}`);
|
|
188
|
-
console.log(` nachher : ${mb(b.nachher)}`);
|
|
189
|
-
console.log(` gespart : ${mb(b.vorher - b.nachher)} (Faktor ${(b.vorher / Math.max(1, b.nachher)).toFixed(2)})`);
|
|
190
|
-
console.log('');
|
|
191
|
-
console.log(schreiben ? ' GESCHRIEBEN.' : ' TROCKENLAUF — nichts veraendert. Mit --schreiben ausfuehren.');
|
|
192
|
-
}
|
|
193
|
-
finally {
|
|
194
|
-
redis.disconnect();
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
const direktGestartet = process.argv[1]?.replace(/\\/g, '/').endsWith('/vektoren-verdichten.ts');
|
|
198
|
-
if (direktGestartet)
|
|
199
|
-
main().catch((e) => { console.error('FEHLER:', e); process.exit(1); });
|
|
200
|
-
//# sourceMappingURL=vektoren-verdichten.js.map
|
|
1
|
+
import{readFileSync as k,writeFileSync as O,existsSync as R}from"node:fs";import{Redis as L}from"ioredis";import{packe as E,entpacke as m}from"../bedeutung.js";async function p(n,r){const e=[];let s="0";do{const[l,t]=await n.scan(s,"MATCH",r,"COUNT",500);s=l,e.push(...t)}while(s!=="0");return e}function x(n){const r=Buffer.from(n,"base64");return r.byteLength>7&&r[0]===1&&r.byteLength%4===1}async function N(n,r){const e={schluessel:0,felder:0,vorher:0,nachher:0,uebersprungen:0};for(const s of["cachly:lesson:vec:*","cachly:lesson:vecname:*"])for(const l of await p(n,s)){const t=await n.get(l);if(!t)continue;if(e.schluessel++,x(t)){e.uebersprungen++,e.vorher+=t.length,e.nachher+=t.length;continue}const o=m(t);if(!o){e.uebersprungen++;continue}const c=E(o);e.vorher+=t.length,e.nachher+=c.length,e.felder++,r&&await n.set(l,c)}for(const s of await p(n,"cachly:lesson:eing:*")){const l=await n.hgetall(s),t=[];e.schluessel++;for(const[o,c]of Object.entries(l)){if(x(c)){e.uebersprungen++,e.vorher+=c.length,e.nachher+=c.length;continue}const h=m(c);if(!h){e.uebersprungen++;continue}const g=E(h);e.vorher+=c.length,e.nachher+=g.length,e.felder++,t.push(o,g)}r&&t.length>0&&await n.hset(s,...t)}return e}const y=n=>`${(n/1024/1024).toFixed(2)} MB`;async function C(){const n=process.argv.slice(2),r=c=>{const h=n.indexOf(`--${c}`);return h!==-1?n[h+1]:void 0},e=process.env.CACHLY_REDIS_URL??process.env.REDIS_URL;e||(console.error("NICHT GELAUFEN: REDIS_URL fehlt."),process.exit(2));const s=r("sicherung");s||(console.error("NICHT GELAUFEN: --sicherung <datei> fehlt."),process.exit(2));const l=n.includes("--schreiben"),t=n.includes("--zurueck"),o=new L(e,{maxRetriesPerRequest:2,connectTimeout:8e3});try{if(t){R(s)||(console.error(`NICHT GELAUFEN: Sicherung fehlt (${s}).`),process.exit(2));const a=JSON.parse(k(s,"utf8"));let f=0;for(const[u,w]of Object.entries(a.werte))await o.set(u,w),f++;for(const[u,w]of Object.entries(a.hashes)){const $=Object.entries(w).flat();$.length!==0&&(await o.del(u),await o.hset(u,...$),f++)}console.log(`ZURUECKGESPIELT: ${f} Schluessel aus ${s}`);return}const c={},h={};for(const a of["cachly:lesson:vec:*","cachly:lesson:vecname:*"])for(const f of await p(o,a)){const u=await o.get(f);u&&(c[f]=u)}for(const a of await p(o,"cachly:lesson:eing:*"))h[a]=await o.hgetall(a);O(s,JSON.stringify({werte:c,hashes:h}),{encoding:"utf8"});const g=JSON.parse(k(s,"utf8")),b=Object.keys(c).length,d=Object.keys(g.werte).length,S=Object.keys(h).length,v=Object.keys(g.hashes).length;(b!==d||S!==v||b===0)&&(console.error(`ABBRUCH: Sicherung unvollstaendig (${d}/${b} Werte, ${v}/${S} Hashes).`),process.exit(3)),console.log(`Sicherung geprueft: ${d} Werte + ${v} Hashes in ${s}`);const i=await N(o,l);console.log(""),console.log(` Schluessel angesehen : ${i.schluessel}`),console.log(` Vektoren umgeschrieben: ${i.felder}`),console.log(` uebersprungen : ${i.uebersprungen} (schon int8 oder unlesbar)`),console.log(` vorher : ${y(i.vorher)}`),console.log(` nachher : ${y(i.nachher)}`),console.log(` gespart : ${y(i.vorher-i.nachher)} (Faktor ${(i.vorher/Math.max(1,i.nachher)).toFixed(2)})`),console.log(""),console.log(l?" GESCHRIEBEN.":" TROCKENLAUF \u2014 nichts veraendert. Mit --schreiben ausfuehren.")}finally{o.disconnect()}}const I=process.argv[1]?.replace(/\\/g,"/").endsWith("/vektoren-verdichten.ts");I&&C().catch(n=>{console.error("FEHLER:",n),process.exit(1)});export{p as alleSchluessel,x as istInt8,N as verdichte};
|
|
@@ -1,72 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Welche der 122 Werkzeuge werden wirklich benutzt?
|
|
3
|
-
*
|
|
4
|
-
* ANLASS 19.08.2026: Die Glama-Bewertung sagt, cachly habe zu viele Werkzeuge
|
|
5
|
-
* und viele liessen sich zusammenlegen. Der Einwand ist plausibel — nur konnte
|
|
6
|
-
* ihm niemand mit Zahlen begegnen, weil es KEINE Messung gab. Nirgends im
|
|
7
|
-
* Server wurde festgehalten, welches Werkzeug wie oft gerufen wird.
|
|
8
|
-
*
|
|
9
|
-
* Ohne diese Zahl ist jedes Zusammenlegen geraten. Man streicht dann das, was
|
|
10
|
-
* man selbst selten benutzt — und das ist selten dasselbe wie das, was die
|
|
11
|
-
* Nutzer selten benutzen.
|
|
12
|
-
*
|
|
13
|
-
* Diese Datei ist die Rechnung dazu, ohne Datenzugriff und ohne neues
|
|
14
|
-
* Werkzeug: gezaehlt wird an der EINEN Stelle, durch die jeder Aufruf geht
|
|
15
|
-
* (handleTool), und gelesen wird in `brain_metrics`, das es schon gibt. Ein
|
|
16
|
-
* 123. Werkzeug, um zu messen, dass es zu viele Werkzeuge gibt, waere die
|
|
17
|
-
* Pointe, die niemand will.
|
|
18
|
-
*/
|
|
19
|
-
/** Redis-Hash je Brain: Feld = Werkzeugname, Wert = Anzahl der Aufrufe. */
|
|
20
|
-
export function nutzungsSchluessel(instanceId) {
|
|
21
|
-
return `cachly:stats:tool_calls:${instanceId}`;
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Rohzaehler zu einem lesbaren Bild verdichten.
|
|
25
|
-
*
|
|
26
|
-
* Rein, damit sich die Verdichtung ohne Redis pruefen laesst. Ungueltige
|
|
27
|
-
* Zaehler (kein Zahlwert, negativ) fallen heraus statt NaN zu erzeugen — eine
|
|
28
|
-
* kaputte Zeile darf nicht die ganze Auswertung vergiften.
|
|
29
|
-
*/
|
|
30
|
-
export function verdichte(roh, spitzeN = 15) {
|
|
31
|
-
const zeilen = [];
|
|
32
|
-
for (const [name, wert] of Object.entries(roh)) {
|
|
33
|
-
const n = typeof wert === 'number' ? wert : Number(wert);
|
|
34
|
-
if (!Number.isFinite(n) || n <= 0)
|
|
35
|
-
continue;
|
|
36
|
-
zeilen.push({ name, aufrufe: Math.floor(n) });
|
|
37
|
-
}
|
|
38
|
-
const gesamt = zeilen.reduce((s, z) => s + z.aufrufe, 0);
|
|
39
|
-
zeilen.sort((a, b) => b.aufrufe - a.aufrufe || a.name.localeCompare(b.name));
|
|
40
|
-
const spitze = zeilen.slice(0, Math.max(0, spitzeN)).map((z) => ({
|
|
41
|
-
...z,
|
|
42
|
-
anteil: gesamt > 0 ? z.aufrufe / gesamt : 0,
|
|
43
|
-
}));
|
|
44
|
-
const summeSpitze = spitze.reduce((s, z) => s + z.aufrufe, 0);
|
|
45
|
-
return {
|
|
46
|
-
gesamt,
|
|
47
|
-
benutzte: zeilen.length,
|
|
48
|
-
spitze,
|
|
49
|
-
anteilSpitze: gesamt > 0 ? summeSpitze / gesamt : 0,
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Der Satz, der die Glama-Frage beantwortet.
|
|
54
|
-
*
|
|
55
|
-
* Bewusst mit der Zahl der NIE gerufenen Werkzeuge: das ist die Angabe, an der
|
|
56
|
-
* sich entscheidet, ob zusammengelegt werden sollte — und sie ist unbequem
|
|
57
|
-
* genug, dass niemand sie schoenreden kann.
|
|
58
|
-
*
|
|
59
|
-
* Ohne einen einzigen Aufruf wird NICHT behauptet, alles sei ungenutzt: eine
|
|
60
|
-
* frische Instanz hat noch nichts gemessen, und "0 von 122 benutzt" waere dann
|
|
61
|
-
* eine Aussage ueber die Messung, nicht ueber das Produkt.
|
|
62
|
-
*/
|
|
63
|
-
export function nutzungInWorten(bild, werkzeugeGesamt) {
|
|
64
|
-
if (bild.gesamt === 0) {
|
|
65
|
-
return 'Noch keine Werkzeug-Aufrufe gezählt — die Messung beginnt mit dem nächsten Aufruf.';
|
|
66
|
-
}
|
|
67
|
-
const nie = Math.max(0, werkzeugeGesamt - bild.benutzte);
|
|
68
|
-
const prozent = Math.round(bild.anteilSpitze * 100);
|
|
69
|
-
return (`${bild.benutzte} von ${werkzeugeGesamt} Werkzeugen wurden hier je gerufen (${nie} nie). ` +
|
|
70
|
-
`Die ${bild.spitze.length} häufigsten tragen ${prozent} % aller ${bild.gesamt} Aufrufe.`);
|
|
71
|
-
}
|
|
72
|
-
//# sourceMappingURL=werkzeug-nutzung.js.map
|
|
1
|
+
function i(t){return`cachly:stats:tool_calls:${t}`}function c(t,o=15){const u=[];for(const[e,n]of Object.entries(t)){const f=typeof n=="number"?n:Number(n);!Number.isFinite(f)||f<=0||u.push({name:e,aufrufe:Math.floor(f)})}const r=u.reduce((e,n)=>e+n.aufrufe,0);u.sort((e,n)=>n.aufrufe-e.aufrufe||e.name.localeCompare(n.name));const s=u.slice(0,Math.max(0,o)).map(e=>({...e,anteil:r>0?e.aufrufe/r:0})),a=s.reduce((e,n)=>e+n.aufrufe,0);return{gesamt:r,benutzte:u.length,spitze:s,anteilSpitze:r>0?a/r:0}}function m(t,o){if(t.gesamt===0)return"Noch keine Werkzeug-Aufrufe gez\xE4hlt \u2014 die Messung beginnt mit dem n\xE4chsten Aufruf.";const u=Math.max(0,o-t.benutzte),r=Math.round(t.anteilSpitze*100);return`${t.benutzte} von ${o} Werkzeugen wurden hier je gerufen (${u} nie). Die ${t.spitze.length} h\xE4ufigsten tragen ${r} % aller ${t.gesamt} Aufrufe.`}export{m as nutzungInWorten,i as nutzungsSchluessel,c as verdichte};
|
package/dist/src/wertbeitrag.js
CHANGED
|
@@ -1,203 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* Wertbeitrag — was ein einzelner Abruf zur Zeitersparnis beiträgt.
|
|
3
|
-
*
|
|
4
|
-
* ─── DER ANLASS ────────────────────────────────────────────────────────────
|
|
5
|
-
*
|
|
6
|
-
* Am 17.08.2026 zeigte das Panel eines Brains mit 475 Lektionen eine
|
|
7
|
-
* Zeitersparnis von 54 Tagen und einen Gegenwert von 97.237,50 €. Nachgerechnet
|
|
8
|
-
* stammte praktisch die ganze Zahl aus dem STARTER-KORPUS: `docker:layer-cache`
|
|
9
|
-
* stand bei 973 Abrufen, `cache:stampede` bei 971, dahinter neun weitere
|
|
10
|
-
* Starter-Lektionen mit je rund 208. Die echten, projektbezogenen Lektionen
|
|
11
|
-
* standen bei zwei bis fünf.
|
|
12
|
-
*
|
|
13
|
-
* Der Starter-Korpus ist genau das, wofür er gedacht ist: ein Startvorrat, der
|
|
14
|
-
* dafür sorgt, dass die erste Frage an ein leeres Brain nicht ins Leere geht.
|
|
15
|
-
* Er ist eingekauftes Allgemeinwissen — Docker-Cache, JWT-Uhrzeitversatz,
|
|
16
|
-
* N+1-Abfragen. Er ist NICHT das, was jemand über sein Projekt gelernt hat.
|
|
17
|
-
*
|
|
18
|
-
* Ihn in die Wertschätzung einzurechnen macht die Zahl doppelt falsch:
|
|
19
|
-
* - Sie wächst, ohne dass jemand etwas gelernt hat.
|
|
20
|
-
* - Sie wächst am schnellsten in Brains, die am wenigsten eigenes Wissen
|
|
21
|
-
* haben — dort gibt es ja nichts anderes zu treffen.
|
|
22
|
-
*
|
|
23
|
-
* Eine Kennzahl, die dann am besten aussieht, wenn das Produkt am wenigsten
|
|
24
|
-
* leistet, ist schlimmer als gar keine.
|
|
25
|
-
*
|
|
26
|
-
* ─── WARUM KEINE NAMENSLISTE ───────────────────────────────────────────────
|
|
27
|
-
*
|
|
28
|
-
* Naheliegend wäre gewesen, die sechs auffälligen Themen hart auszuschliessen.
|
|
29
|
-
* Das wäre ein Wächter, der auf den Anlass genagelt ist: Beim nächsten
|
|
30
|
-
* Starter-Korpus mit anderen Namen wäre er blind. Die Starter-Lektionen tragen
|
|
31
|
-
* seit ihrer Einführung `source: 'starter'` im Datensatz — genau dafür. Diese
|
|
32
|
-
* Datei benutzt die Markierung, nicht die Namen.
|
|
33
|
-
*
|
|
34
|
-
* ─── NACHTRAG 22.08.2026: DIE MARKIERUNG GAB ES NICHT ──────────────────────
|
|
35
|
-
*
|
|
36
|
-
* Der Absatz darüber stand fünf Tage lang so da und war falsch. Gemessen in
|
|
37
|
-
* der Gegenrede über die Zahl „Brain saved you ~1664h":
|
|
38
|
-
*
|
|
39
|
-
* brain_hygiene(dry_run) → "Startvorrat entwertet (Zähler auf 0): 0"
|
|
40
|
-
* bei 543 gescannten Lektionen.
|
|
41
|
-
*
|
|
42
|
-
* NULL. Der Filter griff bei keiner einzigen. `docker:layer-cache` — der
|
|
43
|
-
* Anlass dieser ganzen Datei — zählte weiterhin voll mit inzwischen 974
|
|
44
|
-
* Abrufen.
|
|
45
|
-
*
|
|
46
|
-
* Der Grund: Die eingebauten Lektionen kommen über `import_public_brain`
|
|
47
|
-
* herein und tragen dabei gar kein `source`-Feld. Die Markierung, auf die
|
|
48
|
-
* sich der Absatz oben verlässt, wird beim Schreiben nie gesetzt.
|
|
49
|
-
*
|
|
50
|
-
* Das ist die eigentliche Lehre, und sie ist unbequemer als die erste: Der
|
|
51
|
-
* Fix war gebaut, beschrieben und begründet — und hat nie gewirkt. Niemand
|
|
52
|
-
* hat nachgemessen, ob er greift. Fünf Tage lang stand in dieser Datei ein
|
|
53
|
-
* Kommentar über einen Schutz, den es nicht gab.
|
|
54
|
-
*
|
|
55
|
-
* Deshalb prüft `istStarterLektion` jetzt drei Dinge (Herkunft, Thema,
|
|
56
|
-
* fremder Installationsweg) — und deshalb steht darunter eine Probe, die
|
|
57
|
-
* nicht den Code liest, sondern eine echte Lektion durch die Funktion
|
|
58
|
-
* schickt. Ein Kommentar ist kein Beweis.
|
|
59
|
-
*/
|
|
60
|
-
import { STARTER_CORPUS } from './starter-corpus.js';
|
|
61
|
-
/** fmtStunden macht aus Minuten eine lesbare Angabe ("21 h", "3 d 4 h"). */
|
|
62
|
-
export function fmtStunden(minuten) {
|
|
63
|
-
const gesamt = Math.max(0, Math.round(minuten));
|
|
64
|
-
if (gesamt < 60)
|
|
65
|
-
return `${gesamt} min`;
|
|
66
|
-
const stunden = Math.floor(gesamt / 60);
|
|
67
|
-
if (stunden < 24)
|
|
68
|
-
return `${stunden} h`;
|
|
69
|
-
const tage = Math.floor(stunden / 24);
|
|
70
|
-
const rest = stunden % 24;
|
|
71
|
-
return rest > 0 ? `${tage} d ${rest} h` : `${tage} d`;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Der ausgelieferte Startvorrat, nach Thema aufgeschlagen — ABGELEITET.
|
|
75
|
-
*
|
|
76
|
-
* Erster Versuch am 22.08.2026 war eine von Hand gepflegte Namensliste. Sie war
|
|
77
|
-
* schon beim Schreiben falsch: sieben Themen fehlten, drei standen darin, die
|
|
78
|
-
* es gar nicht gibt. Eine zweite Liste derselben Wahrheit laeuft auseinander,
|
|
79
|
-
* bevor sie fertig ist.
|
|
80
|
-
*/
|
|
81
|
-
const STARTER_NACH_THEMA = new Map(STARTER_CORPUS.map((l) => [l.topic, l.what_worked]));
|
|
82
|
-
/** Die Themen des Startvorrats — fuer Aufrufer, die nur die Namen brauchen. */
|
|
83
|
-
export const STARTER_THEMEN = new Set(STARTER_NACH_THEMA.keys());
|
|
84
|
-
/**
|
|
85
|
-
* Herkuenfte, die NICHT als eigene Lernleistung zaehlen.
|
|
86
|
-
*
|
|
87
|
-
* Es gibt zwei Wege, auf denen fremdes Wissen in ein Brain kommt, und sie
|
|
88
|
-
* schreiben ZWEI VERSCHIEDENE Werte:
|
|
89
|
-
*
|
|
90
|
-
* brain_seed_starter (share.ts) → source: 'starter'
|
|
91
|
-
* import_public_brain (team.ts) → source: 'public_brain'
|
|
92
|
-
*
|
|
93
|
-
* `marketplace:` und `syndicate:` sind vorgemerkt, damit der naechste
|
|
94
|
-
* Einbauweg nicht wieder still durchrutscht.
|
|
95
|
-
*/
|
|
96
|
-
const FREMDE_HERKUNFT = /^(starter|public_brain|marketplace:|syndicate:|import)/;
|
|
97
|
-
/**
|
|
98
|
-
* Stammt die Lektion aus fremdem Wissen statt aus eigener Arbeit?
|
|
99
|
-
*
|
|
100
|
-
* Solche Lektionen duerfen abgerufen werden und sind nuetzlich — sie zaehlen
|
|
101
|
-
* nur nicht als etwas, das dieser Mensch oder dieses Team gelernt hat.
|
|
102
|
-
*
|
|
103
|
-
* ── NACHTRAG 22.08.2026: der Filter kannte nur die Haelfte ──────────────────
|
|
104
|
-
*
|
|
105
|
-
* Der Schutz war seit dem 17.08. gebaut, beschrieben und begruendet — und hat
|
|
106
|
-
* die groesste Einzelquelle nie erwischt. Er pruefte:
|
|
107
|
-
*
|
|
108
|
-
* return lesson?.source === 'starter';
|
|
109
|
-
*
|
|
110
|
-
* `import_public_brain` schreibt aber `source: 'public_brain'` (team.ts:1610),
|
|
111
|
-
* und dahinter steht eine EIGENE eingebaute Liste von rund 40 Lektionen ueber
|
|
112
|
-
* go, docker, kubernetes, react, typescript und python — darunter
|
|
113
|
-
* `docker:layer-cache`, die meistabgerufene Lektion dieses Brains ueberhaupt
|
|
114
|
-
* (980 Abrufe, gemessen am 22.08.2026).
|
|
115
|
-
*
|
|
116
|
-
* Ein Vergleich auf genau eine Zeichenkette ist blind fuer den zweiten Weg.
|
|
117
|
-
* Und weil `brain_hygiene` (team.ts:1247) die Zeitersparnis aus derselben
|
|
118
|
-
* Funktion NEU rechnet, machte die Luecke die Zahl nicht nur zu gross, sondern
|
|
119
|
-
* beim Aufraeumen noch groesser: 1664 h → 6445 h.
|
|
120
|
-
*
|
|
121
|
-
* ── Warum trotzdem nicht nur ueber die Namen ────────────────────────────────
|
|
122
|
-
*
|
|
123
|
-
* Eine reine Namensliste wuerde eine echte Regel brechen: Wer selbst etwas
|
|
124
|
-
* ueber `docker:layer-cache` lernt, hat etwas gelernt. Deshalb entscheidet
|
|
125
|
-
* zuerst die Herkunft. Nur wenn gar keine dasteht — `learn_from_attempts`
|
|
126
|
-
* setzt das Feld nicht — wird das Thema geprueft, und dann muss auch der TEXT
|
|
127
|
-
* wortgleich der ausgelieferte sein. Ein eigener Satz zum selben Thema zaehlt.
|
|
128
|
-
*/
|
|
129
|
-
export function istStarterLektion(lesson) {
|
|
130
|
-
if (!lesson)
|
|
131
|
-
return false;
|
|
132
|
-
if (typeof lesson.source === 'string' && lesson.source !== '') {
|
|
133
|
-
// Herkunft steht da: sie entscheidet, in beide Richtungen.
|
|
134
|
-
return FREMDE_HERKUNFT.test(lesson.source);
|
|
135
|
-
}
|
|
136
|
-
// Keine Herkunft: nur ein WORTGLEICHER Treffer aus dem Vorrat zaehlt nicht.
|
|
137
|
-
if (typeof lesson.topic !== 'string')
|
|
138
|
-
return false;
|
|
139
|
-
const ausgeliefert = STARTER_NACH_THEMA.get(lesson.topic);
|
|
140
|
-
if (ausgeliefert === undefined)
|
|
141
|
-
return false;
|
|
142
|
-
const eigener = typeof lesson.what_worked === 'string' ? lesson.what_worked : '';
|
|
143
|
-
return eigener.trim() === ausgeliefert.trim();
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Minuten, die ein Abruf dieser Lektion einspart — 0 für fremdes Wissen.
|
|
147
|
-
*
|
|
148
|
-
* Die Staffel (30 / 60 / 240) ist unverändert; sie stand vorher an drei
|
|
149
|
-
* Stellen im Code und steht jetzt hier. `basis` erlaubt der abweichenden
|
|
150
|
-
* Staffel von causal_trace (60 / 120 / 240) ihren eigenen Grundwert, ohne dass
|
|
151
|
-
* die Starter-Regel ein zweites Mal geschrieben werden muss.
|
|
152
|
-
*/
|
|
153
|
-
export function ersparteMinuten(lesson, basis = 'recall') {
|
|
154
|
-
if (!lesson || istStarterLektion(lesson))
|
|
155
|
-
return 0;
|
|
156
|
-
const sev = lesson.severity;
|
|
157
|
-
if (sev === 'critical')
|
|
158
|
-
return 240;
|
|
159
|
-
if (sev === 'major')
|
|
160
|
-
return basis === 'trace' ? 120 : 60;
|
|
161
|
-
return basis === 'trace' ? 60 : 30;
|
|
162
|
-
}
|
|
163
|
-
/**
|
|
164
|
-
* Zaehlt dieser Abruf ueberhaupt Zeit — oder ist es ein Wiedersehen?
|
|
165
|
-
*
|
|
166
|
-
* ── DER ZWEITE BEFUND VOM 22.08.2026 ────────────────────────────────────────
|
|
167
|
-
*
|
|
168
|
-
* Der Startvorrat-Filter war nur die halbe Ursache. Die andere Haelfte:
|
|
169
|
-
* Zeitersparnis wurde bei JEDEM Abruf erneut gutgeschrieben.
|
|
170
|
-
*
|
|
171
|
-
* `smart_recall` schreibt bis zu FUENF Lektionen pro Aufruf die volle
|
|
172
|
-
* Recherchezeit gut (brain.ts:1725 ff.). Die Anleitung des Servers verlangt
|
|
173
|
-
* einen Aufruf "BEFORE every task", und eingeblendete Lektionen kommen
|
|
174
|
-
* zusaetzlich bei jedem Prompt. Zehn Aufgaben in einer Sitzung konnten so
|
|
175
|
-
* rechnerisch zweihundert Stunden erzeugen.
|
|
176
|
-
*
|
|
177
|
-
* Gemessen: Dieses Brain ist am 01.06.2026 entstanden, 82 Tage alt, und meldete
|
|
178
|
-
* 1664,5 Stunden. Eine Person haette in 82 Tagen zu acht Stunden 656 Stunden
|
|
179
|
-
* gehabt. Die Zahl war nicht zu hoch — sie war unmoeglich.
|
|
180
|
-
*
|
|
181
|
-
* ── Die Regel, die haelt ────────────────────────────────────────────────────
|
|
182
|
-
*
|
|
183
|
-
* Die Zusage lautet "time not re-researching known fixes". Recherchiert wird
|
|
184
|
-
* EINMAL. Wer dieselbe Lektion zum neunhundertsten Mal sieht, spart nicht zum
|
|
185
|
-
* neunhundertsten Mal eine Recherche — er spart ein Nachschlagen.
|
|
186
|
-
*
|
|
187
|
-
* Also: jede Lektion zaehlt genau EINMAL, beim ersten Abruf. Damit ist die
|
|
188
|
-
* Zahl nach oben durch den Wissensstand begrenzt statt durch die Nutzung, sie
|
|
189
|
-
* kann nicht mehr schneller wachsen als gelernt wird — und das Einblenden
|
|
190
|
-
* treibt sie gar nicht mehr.
|
|
191
|
-
*
|
|
192
|
-
* Das ist dieselbe Fehlerklasse wie `cachly:metric-inflation-fixed` (PR #158,
|
|
193
|
-
* stuendliche Heartbeat-Pings blaehten die ROI-Zahlen auf). Damals wurde die
|
|
194
|
-
* eine Quelle abgestellt; die Bauart, die aus Wiederholung Wert macht, blieb.
|
|
195
|
-
*/
|
|
196
|
-
export function zaehltAlsErsparnis(lesson) {
|
|
197
|
-
if (!lesson || istStarterLektion(lesson))
|
|
198
|
-
return false;
|
|
199
|
-
// recall_count ist der Stand VOR diesem Abruf. 0 heisst: das erste Mal.
|
|
200
|
-
const bisher = typeof lesson.recall_count === 'number' ? lesson.recall_count : 0;
|
|
201
|
-
return bisher <= 0;
|
|
202
|
-
}
|
|
203
|
-
//# sourceMappingURL=wertbeitrag.js.map
|
|
1
|
+
import{STARTER_CORPUS as a}from"./starter-corpus.js";function p(t){const r=Math.max(0,Math.round(t));if(r<60)return`${r} min`;const e=Math.floor(r/60);if(e<24)return`${e} h`;const n=Math.floor(e/24),i=e%24;return i>0?`${n} d ${i} h`:`${n} d`}const c=new Map(a.map(t=>[t.topic,t.what_worked])),m=new Set(c.keys()),u=/^(starter|public_brain|marketplace:|syndicate:|import)/;function o(t){if(!t)return!1;if(typeof t.source=="string"&&t.source!=="")return u.test(t.source);if(typeof t.topic!="string")return!1;const r=c.get(t.topic);return r===void 0?!1:(typeof t.what_worked=="string"?t.what_worked:"").trim()===r.trim()}function h(t,r="recall"){if(!t||o(t))return 0;const e=t.severity;return e==="critical"?240:e==="major"?r==="trace"?120:60:r==="trace"?60:30}function s(t){return!t||o(t)?!1:(typeof t.recall_count=="number"?t.recall_count:0)<=0}export{m as STARTER_THEMEN,h as ersparteMinuten,p as fmtStunden,o as istStarterLektion,s as zaehltAlsErsparnis};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const d=500,m=500;function o(e,t){return typeof e=="string"?e.trim().slice(0,t):""}function p(e,t){const r=o(e.frage,500);if(!r)return{ok:!1,grund:"frage fehlt \u2014 ohne die Frage ist der Eintrag wertlos"};const n=o(e.thema,200);return n?typeof e.geholfen!="boolean"?{ok:!1,grund:'geholfen muss true oder false sein \u2014 "weiss nicht" ist keine Rueckmeldung'}:typeof e.platz!="number"||!Number.isInteger(e.platz)||e.platz<0?{ok:!1,grund:"platz muss eine ganze Zahl ab 0 sein (0 = die Lektion stand gar nicht in der Antwort)"}:{ok:!0,eintrag:{ts:t,quelle:"gemeldet",frage:r,thema:n,geholfen:e.geholfen,platz:e.platz,notiz:o(e.notiz,500),autor:o(e.autor,80)}}:{ok:!1,grund:"thema fehlt \u2014 welche Lektion ist gemeint?"}}function A(e,t,r){if(!e)return null;const n=o(e.frage,500),f=o(t,200);if(!n||!f||!Array.isArray(e.themen))return null;const l=e.themen.indexOf(f);return{ts:r,quelle:"abgeleitet",frage:n,thema:f,geholfen:!0,platz:l===-1?0:l+1,notiz:l===-1?"automatisch: geoeffnet, obwohl nicht in der Antwort":"automatisch: aus der Antwort geoeffnet",autor:""}}const a=3;function c(e){return e.geholfen&&e.platz===0?"fehlender-treffer":e.geholfen&&e.platz>a?"zu-weit-hinten":!e.geholfen&&e.platz>0&&e.platz<=a?"falsch-und-sicher":e.geholfen?"bestaetigung":"unauffaellig"}function z(e){const t={"fehlender-treffer":0,"zu-weit-hinten":0,"falsch-und-sicher":0,bestaetigung:0,unauffaellig:0};let r=0,n=0,f=0,l=0,s=0,u=0,h=0;for(const i of e){t[c(i)]++;const g=i.platz>0&&i.platz<=a;if(i.quelle==="abgeleitet"){n++,u++,g&&h++;continue}r++,i.geholfen&&(f++,l++,g&&s++)}return{gesamt:e.length,gemeldet:r,abgeleitet:n,geholfen:f,trefferquote:l===0?null:s/l,auswahlquote:u===0?null:h/u,nachLehrwert:t}}export{a as SICHTBARE_PLAETZE,c as lehrwert,A as leiteAb,p as pruefeWirkung,z as werteAus};
|
package/glama.json
CHANGED
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cachly-dev/mcp-server",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.131",
|
|
4
4
|
"mcpName": "io.github.cachly-dev/mcp-server",
|
|
5
|
-
"description": "Your AI forgets everything between sessions. cachly fixes that permanently:
|
|
5
|
+
"description": "Your AI forgets everything between sessions. cachly fixes that permanently: 123 MCP tools for Claude Code, Cursor, Copilot & Windsurf. Learns from every bug fix, commit and CI run. Arrives pre-briefed. Free tier forever, EU servers, GDPR.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"files": [
|
|
8
|
-
"dist/index
|
|
9
|
-
"dist/src
|
|
10
|
-
"dist/packages
|
|
8
|
+
"dist/index.js",
|
|
9
|
+
"dist/src/**/*.js",
|
|
10
|
+
"dist/packages/**/*.js",
|
|
11
11
|
"scripts/postinstall.js",
|
|
12
12
|
"server.json",
|
|
13
13
|
"glama.json"
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"verify-tool-spec-snapshots": "node scripts/tool-spec-snapshots.mjs check",
|
|
33
33
|
"verify-tool-counts": "node scripts/verify-tool-counts.mjs",
|
|
34
34
|
"verify-capabilities": "node scripts/verify-capabilities.mjs",
|
|
35
|
-
"build": "tsc && node scripts/bauabdruck.mjs",
|
|
35
|
+
"build": "tsc && node scripts/paket-schliessen.mjs && node scripts/bauabdruck.mjs",
|
|
36
36
|
"postinstall": "node scripts/postinstall.js",
|
|
37
37
|
"dev": "tsx src/index.ts",
|
|
38
38
|
"start": "node dist/src/index.js",
|
|
@@ -60,6 +60,7 @@
|
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@eslint/js": "^9.39.4",
|
|
62
62
|
"@types/node": "^22",
|
|
63
|
+
"esbuild": "^0.28.2",
|
|
63
64
|
"eslint": "^9",
|
|
64
65
|
"gpt-tokenizer": "^3.4.0",
|
|
65
66
|
"tsx": "^4.23.12",
|
|
@@ -68,7 +69,7 @@
|
|
|
68
69
|
"vitest": "^3.2.4"
|
|
69
70
|
},
|
|
70
71
|
"overrides": {
|
|
71
|
-
"esbuild": "
|
|
72
|
+
"esbuild": "$esbuild"
|
|
72
73
|
},
|
|
73
74
|
"engines": {
|
|
74
75
|
"node": ">=20"
|
package/server.json
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.cachly-dev/mcp-server",
|
|
4
|
-
"description": "Persistent memory + causal root-cause analysis for AI coding agents.
|
|
4
|
+
"description": "Persistent memory + causal root-cause analysis for AI coding agents. 123 MCP tools. EU, GDPR.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"url": "https://github.com/cachly-dev/cachly-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.10.
|
|
9
|
+
"version": "0.10.131",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"name": "@cachly-dev/mcp-server",
|
|
14
14
|
"identifier": "@cachly-dev/mcp-server",
|
|
15
|
-
"version": "0.10.
|
|
15
|
+
"version": "0.10.131",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import './src/index.js';
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,+EAA+E;AAC/E,+EAA+E;AAC/E,4EAA4E;AAC5E,wCAAwC;AACxC,OAAO,gBAAgB,CAAC"}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* telegram-notify — shared Telegram notification client.
|
|
3
|
-
*
|
|
4
|
-
* Used by cachly-mcp (TypeScript) and TCO backend (Python via client.py).
|
|
5
|
-
* Single source of truth for: emoji map, message format, env var convention.
|
|
6
|
-
*
|
|
7
|
-
* Interface: notify(app, event, payload)
|
|
8
|
-
*
|
|
9
|
-
* Env vars:
|
|
10
|
-
* TELEGRAM_BOT_TOKEN — bot token from @BotFather
|
|
11
|
-
* {APP_UPPER}_TELEGRAM_CHAT_ID — app-specific channel (e.g. CACHLY_TELEGRAM_CHAT_ID)
|
|
12
|
-
* TELEGRAM_CHAT_ID — fallback for all apps
|
|
13
|
-
*
|
|
14
|
-
* No-op when unconfigured. Never throws.
|
|
15
|
-
*
|
|
16
|
-
* Note: emoji map is kept in sync with emojis.json (Python reads the JSON file at runtime).
|
|
17
|
-
*/
|
|
18
|
-
export declare function formatMessage(app: string, event: string, payload: Record<string, unknown>): string;
|
|
19
|
-
export declare function notify(app: string, event: string, payload?: Record<string, unknown>): Promise<void>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../../packages/telegram-notify/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAKH,MAAM,KAAK,GAA2B;IACpC,SAAS,EAAW,IAAI;IACxB,UAAU,EAAU,IAAI;IACxB,SAAS,EAAW,GAAG;IACvB,UAAU,EAAU,IAAI;IACxB,OAAO,EAAa,IAAI;IACxB,SAAS,EAAW,IAAI;IACxB,OAAO,EAAa,IAAI;IACxB,eAAe,EAAK,IAAI;IACxB,UAAU,EAAU,IAAI;IACxB,UAAU,EAAU,IAAI;IACxB,SAAS,EAAW,IAAI;IACxB,YAAY,EAAQ,KAAK;IACzB,YAAY,EAAQ,KAAK;IACzB,KAAK,EAAe,IAAI;IACxB,cAAc,EAAM,IAAI;IACxB,eAAe,EAAK,IAAI;IACxB,QAAQ,EAAY,IAAI;IACxB,UAAU,EAAU,IAAI;IACxB,WAAW,EAAS,IAAI;IACxB,OAAO,EAAa,IAAI;CACzB,CAAC;AAEF,SAAS,QAAQ;IACf,OAAO,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,SAAS,CAAC,GAAW;IAC5B,MAAM,GAAG,GAAG,GAAG,GAAG,CAAC,WAAW,EAAE,mBAAmB,CAAC;IACpD,OAAO,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,GAAW,EACX,KAAa,EACb,OAAgC;IAEhC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,KAAK,GAAG,CAAC,WAAW,EAAE,SAAS,KAAK,IAAI,CAAC,CAAC;IAChE,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QAC7C,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,GAAW,EACX,KAAa,EACb,UAAmC,EAAE;IAErC,MAAM,KAAK,GAAG,QAAQ,EAAE,CAAC;IACzB,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;QAAE,OAAO;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;QAChD,MAAM,KAAK,CAAC,+BAA+B,KAAK,cAAc,EAAE;YAC9D,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC;YACvE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;AACH,CAAC"}
|