@cachly-dev/mcp-server 0.10.197 → 0.10.198

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.
@@ -0,0 +1 @@
1
+ import{kosinus as P}from"./bedeutung.js";import{DOPPEL_SCHWELLE as _}from"./rangfolge-stellschrauben.js";const f="cachly:doppel:kandidaten",w=40,x=14,T=30,d=90*86400,y=6,E=864e5,D=t=>typeof t.what_worked=="string"?t.what_worked.trim().length:0;function k(t,e,o,n=_){return t.topic===e.topic||!(o>=n)||D(t)<w||D(e)<w?!1:!(t.ersetzt===e.topic||t.ersetzt_durch===e.topic||e.ersetzt===t.topic||e.ersetzt_durch===t.topic)}function O(t,e){let o=null;for(const n of e)k(t,n.lektion,n.naehe)&&(!o||n.naehe>o.naehe)&&(o={topic:n.lektion.topic,naehe:n.naehe});return o}function g(t){if(!t)return null;try{const e=JSON.parse(t);return e&&typeof e=="object"?e:null}catch{return null}}const S=t=>Math.round(t*1e3)/1e3;async function v(t,e,o,n,c=new Date){try{await n.aktualisiere(t);const i=n.aehnlichste(o,y+1).filter(l=>l.topic!==e.topic&&l.naehe>=_);let a=null;if(i.length>0){const l=await t.mget(...i.map(u=>`cachly:lesson:best:${u.topic}`)),h=i.flatMap((u,L)=>{const m=g(l[L]);return m?[{lektion:{...m,topic:u.topic},naehe:u.naehe}]:[]});a=O(e,h)}const p=await t.hgetall(f),r=Object.entries(p).filter(([l,h])=>l===e.topic||c.getTime()-Date.parse(String(g(h)?.am??""))>T*E||!g(h)).map(([l])=>l);if(r.length>0&&await t.hdel(f,...r),!a)return null;const s={neu:e.topic,alt:a.topic,naehe:S(a.naehe),am:c.toISOString()};return await t.hset(f,e.topic,JSON.stringify({alt:s.alt,naehe:s.naehe,am:s.am})),await t.expire(f,d),s}catch{return null}}async function M(t,e,o=new Date){try{const n=await t.hgetall(f),c=new Map(e.map(a=>[a.topic,a])),i=[];for(const[a,p]of Object.entries(n)){const r=g(p);if(!r||typeof r.alt!="string")continue;const s=String(r.am??"");if(!(o.getTime()-Date.parse(s)<=x*E))continue;const l=c.get(a),h=c.get(r.alt),u=Number(r.naehe);!l||!h||!k(l,h,u)||i.push({neu:a,alt:r.alt,naehe:u,am:s})}return i.sort((a,p)=>p.naehe-a.naehe)}catch{return[]}}function z(t){const e=[];for(let o=0;o<t.length;o++)for(let n=o+1;n<t.length;n++){const c=t[o],i=t[n],a=P(c.vektor,i.vektor);if(!k(c.lektion,i.lektion,a))continue;const p=String(c.lektion.ts??"")>=String(i.lektion.ts??""),[r,s]=p?[c.lektion,i.lektion]:[i.lektion,c.lektion];e.push({neu:r.topic,alt:s.topic,naehe:S(a)})}return e.sort((o,n)=>n.naehe-o.naehe)}export{x as DOPPEL_BRIEFING_TAGE,T as DOPPEL_HALTEN_TAGE,w as DOPPEL_MINDEST_TEXT,f as DOPPEL_SCHLUESSEL,d as DOPPEL_TTL_S,z as doppelPaare,M as leseDoppelKandidaten,v as pruefeDoppelung,O as waehleDoppelKandidat,k as zaehltAlsDoppelung};
@@ -1,12 +1,12 @@
1
- import{ckgSlug as I}from"../ckg.js";import{safeJsonParse as x,darfHeraus as N}from"../utils.js";import{ersparteMinuten as K,zaehltAlsErsparnis as O}from"../wertbeitrag.js";import{findePaare as F}from"../zulassung-und-urteil.js";import{sofortAntwortNeuesBrain as P}from"../leeres-brain.js";import{fuerWeitergabe as U}from"../schreibtor.js";function E(C){return N(C)&&!C.group}const J=new Set(["memory_consolidate","brain_diff","causal_trace","knowledge_decay","autopilot"]);async function Y(C,A,M,L){switch(C){case"memory_consolidate":{const{instance_id:l,dry_run:p=!1,stale_days:$=90}=A,m=await M(l),g=Date.now(),d=$*86400*1e3;let u=0;const _=[];do{const[n,a]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(n),_.push(...a)}while(u!==0);if(_.length===0)return"\u{1F9E0} **Brain is empty** \u2014 no lessons to consolidate yet. Use `learn_from_attempts` after your next bug fix.";const c=new Map;for(const n of _){const a=await m.get(n);if(!a)continue;const e=x(a,null);e&&c.set(n,e)}const w=new Map;for(const[n,a]of c){const e=a.topic.split(":")[0],o=w.get(e)??[];o.push(n),w.set(e,o)}const y=[...c.values()],b=F(y),v=b.filter(n=>n.beziehung==="widerspruch"),h=b.filter(n=>n.beziehung==="ersetzung"),k=[],s=new Map;for(const[n,a]of c){const e=s.get(a.topic)??[];e.push(n),s.set(a.topic,e)}for(const[n,a]of s)new Set(a.map(o=>c.get(o)?.outcome)).size>1&&k.push({topic:n,keys:a});const t=[];for(const[n,a]of c){const e=g-new Date(a.ts).getTime(),o=a.recall_count??0;e>d&&o===0&&t.push(n)}const i=0;if(!p)for(const n of t)await m.expire(n,86400*30);return[`\u{1F52C} **Memory Consolidation Report** ${p?"(dry run \u2014 no changes made)":"\u2705 Applied"}`,"",`\u{1F4CA} **Before:** ${_.length} lessons`,"",`\u{1F501} **Contradictions \u2014 exact topic match (old rule):** ${k.length}`,`\u{1F50E} **Same subject, admitted for judgement:** ${b.length} \u2192 contradiction ${v.length} \xB7 supersession ${h.length}`,...v.slice(0,5).map(n=>` \u2192 \`${n.a.topic}\` vs \`${n.b.topic}\` (${n.naehe.toFixed(2)}): ${n.grund}`),v.length>5?` \u2026 and ${v.length-5} more`:"",...h.slice(0,3).map(n=>` \u21BB \`${n.a.topic}\` \u2192 \`${n.b.topic}\`: ${n.grund}`),...k.slice(0,5).map(n=>` \u2192 \`${n.topic}\`: ${n.keys.length} conflicting entries (kept: success)`),k.length>5?` \u2026 and ${k.length-5} more`:"","",`\u267B\uFE0F **Duplicate clusters (counted, never deleted):** ${Array.from(w.values()).filter(n=>n.length>1).length}`,"",`\u{1F570}\uFE0F **Stale entries (${$}d, 0 recalls):** ${t.length}`+(t.length>0&&!p?" \u2192 set to expire in 30 days":""),"",`\u{1F4CA} **After:** ${_.length-i} lessons`,"",p?"\u{1F4A1} Re-run without dry_run=true to apply changes.":'\u2728 Brain consolidated. Run `brain_diff(since="1h")` to see the delta.'].filter(n=>n!=="").join(`
2
- `)}case"brain_diff":{const{instance_id:l,since:p="7d",format:$="summary"}=A,m=await M(l);let g;const d=p.match(/^(\d+)([dhm])$/);if(d){const e=parseInt(d[1]),o=d[2],r=o==="d"?864e5:o==="h"?36e5:6e4;g=Date.now()-e*r}else g=new Date(p).getTime()||Date.now()-7*864e5;let u=0;const _=[];do{const[e,o]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(e),_.push(...o)}while(u!==0);const c=[],w=[],y=[],b=_.length;for(const e of _){const o=await m.get(e);if(o){const r=x(o,null);if(!r)continue;if(new Date(r.ts).getTime()>=g){const T=`cachly:lesson:history:${r.topic}`;await m.llen(T)<=1?c.push(r):w.push(r)}(r.recall_count??0)>0&&y.push(r)}}const h=[`\u{1F4CA} **Brain Diff** \u2014 ${d?`last ${p}`:new Date(g).toLocaleDateString("de-DE")}`,"",`Total lessons in brain: **${b}**`,"",`\u2705 **New** (${c.length}):`,...c.slice(0,$==="detailed"?20:5).map(e=>` + \`${e.topic}\` \u2014 ${e.outcome} ${e.severity==="critical"?"\u{1F534}":e.severity==="major"?"\u{1F7E0}":"\u{1F7E2}"}`),c.length>5&&$==="summary"?` \u2026 and ${c.length-5} more`:"","",`\u{1F504} **Updated** (${w.length}):`,...w.slice(0,$==="detailed"?20:5).map(e=>` ~ \`${e.topic}\` \u2014 now: ${e.outcome}`),w.length>5&&$==="summary"?` \u2026 and ${w.length-5} more`:"","",`\u{1F50D} **Active** (recalled at least once): ${y.length}`,""].filter(e=>e!==""),k=[],s=m.scanStream({match:"cachly:ckg:node:resolution-*",count:100});await new Promise((e,o)=>{s.on("data",r=>k.push(...r)),s.on("end",e),s.on("error",o)});const t=[];for(const e of k){const o=await m.get(e);if(o){const r=x(o,null);r?.ts&&new Date(r.ts).getTime()>=g&&t.push({topic:r.topic??e,resolution:r.resolution??"unknown",ts:r.ts})}}if(t.length>0){h.push(`\u{1F5F3}\uFE0F **MADC Resolutions** (${t.length} contested beliefs resolved):`);for(const e of t.slice(0,5)){const o=e.resolution==="unanimous_success"?"\u2705":e.resolution==="unanimous_failure"?"\u274C":"\u26A0\uFE0F";h.push(` ${o} \`${e.topic}\` \u2192 ${e.resolution}`)}h.push("")}const i=new Set(w.concat(y).map(e=>e.topic.split(":")[0])),f=[...new Set(c.map(e=>e.topic.split(":")[0]))].filter(e=>!i.has(e));f.length>0&&h.push(`\u{1F331} **New domains bootstrapped:** ${f.map(e=>`\`${e}\``).join(", ")}`,"");const a=(await m.lrange("cachly:fedbrain:federations",-20,-1)).map(e=>x(e,null)).filter(e=>e!==null&&new Date(e.transferred_at).getTime()>=g);if(a.length>0){h.push(`\u{1F9E0} **FedBrain transfers received (${a.length}):**`);for(const e of a.slice(0,3))h.push(` \u{1F4E5} domain \`${e.domain}\` from \`${e.source.slice(0,16)}\u2026\` \u2014 ${e.nodes} nodes, ${e.edges} edges`);h.push("")}return h.push("\u{1F4A1} Run `memory_consolidate` to merge duplicates \xB7 `knowledge_decay` to see confidence scores."),h.join(`
3
- `)}case"causal_trace":{const{instance_id:l,problem:p,max_depth:$=5,tags:m=[]}=A,g=await P(l,L,`\u{1F50D} **Causal Trace: "${p}"**
1
+ import{ckgSlug as j}from"../ckg.js";import{safeJsonParse as x,darfHeraus as N}from"../utils.js";import{ersparteMinuten as P,zaehltAlsErsparnis as F}from"../wertbeitrag.js";import{findePaare as K}from"../zulassung-und-urteil.js";import{Vektorbestand as O}from"../bedeutung.js";import{doppelPaare as H}from"../doppel-kandidat.js";import{DOPPEL_SCHWELLE as U}from"../rangfolge-stellschrauben.js";import{sofortAntwortNeuesBrain as W}from"../leeres-brain.js";import{fuerWeitergabe as z}from"../schreibtor.js";function B(A){return N(A)&&!A.group}const te=new Set(["memory_consolidate","brain_diff","causal_trace","knowledge_decay","autopilot"]);async function ne(A,S,M,L){switch(A){case"memory_consolidate":{const{instance_id:l,dry_run:g=!1,stale_days:$=90}=S,m=await M(l),w=Date.now(),d=$*86400*1e3;let u=0;const _=[];do{const[n,e]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(n),_.push(...e)}while(u!==0);if(_.length===0)return"\u{1F9E0} **Brain is empty** \u2014 no lessons to consolidate yet. Use `learn_from_attempts` after your next bug fix.";const c=new Map;for(const n of _){const e=await m.get(n);if(!e)continue;const s=x(e,null);s&&c.set(n,s)}const y=new O(0);await y.aktualisiere(m).catch(()=>{});const f=H([...c.values()].flatMap(n=>{const e=y.rohvektor(n.topic);return e?[{lektion:n,vektor:e}]:[]})),k=[...c.values()],b=K(k),h=b.filter(n=>n.beziehung==="widerspruch"),v=b.filter(n=>n.beziehung==="ersetzung"),t=[],o=new Map;for(const[n,e]of c){const s=o.get(e.topic)??[];s.push(n),o.set(e.topic,s)}for(const[n,e]of o)new Set(e.map(i=>c.get(i)?.outcome)).size>1&&t.push({topic:n,keys:e});const a=[];for(const[n,e]of c){const s=w-new Date(e.ts).getTime(),i=e.recall_count??0;s>d&&i===0&&a.push(n)}const r=0;if(!g)for(const n of a)await m.expire(n,86400*30);return[`\u{1F52C} **Memory Consolidation Report** ${g?"(dry run \u2014 no changes made)":"\u2705 Applied"}`,"",`\u{1F4CA} **Before:** ${_.length} lessons`,"",`\u{1F501} **Contradictions \u2014 exact topic match (old rule):** ${t.length}`,`\u{1F50E} **Same subject, admitted for judgement:** ${b.length} \u2192 contradiction ${h.length} \xB7 supersession ${v.length}`,...h.slice(0,5).map(n=>` \u2192 \`${n.a.topic}\` vs \`${n.b.topic}\` (${n.naehe.toFixed(2)}): ${n.grund}`),h.length>5?` \u2026 and ${h.length-5} more`:"",...v.slice(0,3).map(n=>` \u21BB \`${n.a.topic}\` \u2192 \`${n.b.topic}\`: ${n.grund}`),...t.slice(0,5).map(n=>` \u2192 \`${n.topic}\`: ${n.keys.length} conflicting entries (kept: success)`),t.length>5?` \u2026 and ${t.length-5} more`:"","",`\u267B\uFE0F **Possible duplicates \u2014 same meaning, different topic (cosine \u2265 ${U.toFixed(2)}, never merged):** ${f.length}`+(y.groesse===0?" (no vectors in this Brain, so nothing could be compared)":""),...f.slice(0,5).map(n=>` \u2192 \`${n.neu}\` \u2248 \`${n.alt}\` (${n.naehe.toFixed(2)})`),f.length>5?` \u2026 and ${f.length-5} more`:"",f.length>0?' If the newer one replaces the older, pass `ersetzt="<older topic>"` on its next `learn_from_attempts`.':"","",`\u{1F570}\uFE0F **Stale entries (${$}d, 0 recalls):** ${a.length}`+(a.length>0&&!g?" \u2192 set to expire in 30 days":""),"",`\u{1F4CA} **After:** ${_.length-r} lessons`,"",g?"\u{1F4A1} Re-run without dry_run=true to apply changes.":'\u2728 Brain consolidated. Run `brain_diff(since="1h")` to see the delta.'].filter(n=>n!=="").join(`
2
+ `)}case"brain_diff":{const{instance_id:l,since:g="7d",format:$="summary"}=S,m=await M(l);let w;const d=g.match(/^(\d+)([dhm])$/);if(d){const e=parseInt(d[1]),s=d[2],i=s==="d"?864e5:s==="h"?36e5:6e4;w=Date.now()-e*i}else w=new Date(g).getTime()||Date.now()-7*864e5;let u=0;const _=[];do{const[e,s]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(e),_.push(...s)}while(u!==0);const c=[],y=[],f=[],k=_.length;for(const e of _){const s=await m.get(e);if(s){const i=x(s,null);if(!i)continue;if(new Date(i.ts).getTime()>=w){const T=`cachly:lesson:history:${i.topic}`;await m.llen(T)<=1?c.push(i):y.push(i)}(i.recall_count??0)>0&&f.push(i)}}const h=[`\u{1F4CA} **Brain Diff** \u2014 ${d?`last ${g}`:new Date(w).toLocaleDateString("de-DE")}`,"",`Total lessons in brain: **${k}**`,"",`\u2705 **New** (${c.length}):`,...c.slice(0,$==="detailed"?20:5).map(e=>` + \`${e.topic}\` \u2014 ${e.outcome} ${e.severity==="critical"?"\u{1F534}":e.severity==="major"?"\u{1F7E0}":"\u{1F7E2}"}`),c.length>5&&$==="summary"?` \u2026 and ${c.length-5} more`:"","",`\u{1F504} **Updated** (${y.length}):`,...y.slice(0,$==="detailed"?20:5).map(e=>` ~ \`${e.topic}\` \u2014 now: ${e.outcome}`),y.length>5&&$==="summary"?` \u2026 and ${y.length-5} more`:"","",`\u{1F50D} **Active** (recalled at least once): ${f.length}`,""].filter(e=>e!==""),v=[],t=m.scanStream({match:"cachly:ckg:node:resolution-*",count:100});await new Promise((e,s)=>{t.on("data",i=>v.push(...i)),t.on("end",e),t.on("error",s)});const o=[];for(const e of v){const s=await m.get(e);if(s){const i=x(s,null);i?.ts&&new Date(i.ts).getTime()>=w&&o.push({topic:i.topic??e,resolution:i.resolution??"unknown",ts:i.ts})}}if(o.length>0){h.push(`\u{1F5F3}\uFE0F **MADC Resolutions** (${o.length} contested beliefs resolved):`);for(const e of o.slice(0,5)){const s=e.resolution==="unanimous_success"?"\u2705":e.resolution==="unanimous_failure"?"\u274C":"\u26A0\uFE0F";h.push(` ${s} \`${e.topic}\` \u2192 ${e.resolution}`)}h.push("")}const a=new Set(y.concat(f).map(e=>e.topic.split(":")[0])),r=[...new Set(c.map(e=>e.topic.split(":")[0]))].filter(e=>!a.has(e));r.length>0&&h.push(`\u{1F331} **New domains bootstrapped:** ${r.map(e=>`\`${e}\``).join(", ")}`,"");const n=(await m.lrange("cachly:fedbrain:federations",-20,-1)).map(e=>x(e,null)).filter(e=>e!==null&&new Date(e.transferred_at).getTime()>=w);if(n.length>0){h.push(`\u{1F9E0} **FedBrain transfers received (${n.length}):**`);for(const e of n.slice(0,3))h.push(` \u{1F4E5} domain \`${e.domain}\` from \`${e.source.slice(0,16)}\u2026\` \u2014 ${e.nodes} nodes, ${e.edges} edges`);h.push("")}return h.push("\u{1F4A1} Run `memory_consolidate` to merge duplicates \xB7 `knowledge_decay` to see confidence scores."),h.join(`
3
+ `)}case"causal_trace":{const{instance_id:l,problem:g,max_depth:$=5,tags:m=[]}=S,w=await W(l,L,`\u{1F50D} **Causal Trace: "${g}"**
4
4
 
5
- No matching lessons found in brain.`);if(g)return g;const d=await M(l),u=p.toLowerCase().replace(/[^a-z0-9\s\-_:]/g," ").split(/\s+/).filter(t=>t.length>2),_={critical:"\u{1F534}",major:"\u{1F7E0}",minor:"\u{1F7E1}"},c=[];try{for(const t of u.slice(0,4)){const i=await d.smembers(`cachly:ckg:idx:from:${I(t)}`),f=await d.smembers(`cachly:ckg:idx:to:${I(t)}`),n=[],a=d.scanStream({match:`cachly:ckg:node:*${t}*`,count:50});await new Promise((e,o)=>{a.on("data",r=>n.push(...r)),a.on("end",e),a.on("error",o)});for(const e of n.slice(0,10)){const o=await d.get(e);if(!o)continue;const r=x(o,null);if(!r)continue;const D=await d.smembers(`cachly:ckg:idx:from:${r.id}`);for(const T of D.slice(0,20)){const R=await d.get(T);if(!R)continue;const S=x(R,null);if(!S||S.edgeType!=="fixes"&&S.edgeType!=="requires")continue;const j=await d.get(`cachly:lesson:best:${S.from.replace(/-/g,":").replace(/^fix:/,"fix:")}`),B=j?x(j,null)??void 0:void 0;c.push({conceptId:r.id,edge:S,lesson:B&&E(B)?B:void 0})}}for(const e of[...i,...f].slice(0,20)){const o=await d.get(e);if(!o)continue;const r=x(o,null);if(!r)continue;const D=await d.get(`cachly:lesson:best:${r.from}`),T=D?x(D,null)??void 0:void 0;c.push({conceptId:r.from,edge:r,lesson:T&&E(T)?T:void 0})}}}catch{}const w=new Set,y=c.filter(t=>{const i=`${t.edge.from}:${t.edge.edgeType}:${t.edge.to}`;return w.has(i)?!1:(w.add(i),!0)}).sort((t,i)=>i.edge.confidence-t.edge.confidence).slice(0,$);let b=0;const v=[];do{const[t,i]=await d.scan(b,"MATCH","cachly:lesson:*","COUNT",200);b=parseInt(t),v.push(...i)}while(b!==0);const h=[];for(const t of v){const i=await d.get(t);if(i){const f=x(i,null);if(!f||!E(f)||m.length>0&&!(f.tags??[]).some(e=>m.includes(e)))continue;const n=[f.topic,f.what_failed??"",f.what_worked??"",f.context??""].join(" ").toLowerCase(),a=u.reduce((e,o)=>e+(n.includes(o)?1:0),0);a>0&&h.push({score:a,lesson:f,key:t})}}h.sort((t,i)=>i.score-t.score);const k=h.slice(0,$);if(k.length===0&&y.length===0)return[`\u{1F50D} **Causal Trace: "${p}"**`,"","No matching lessons found in brain.","","\u{1F4A1} After you solve this, call:","```","learn_from_attempts(",` instance_id = "${l}",`,` topic = "fix:${u[0]??"issue"}",`,' outcome = "success",',' what_worked = "...",',` what_failed = "${p}",`,")","```"].join(`
6
- `);const s=[`\u{1F50D} **Causal Trace: "${p}"**`,""];if(y.length>0){s.push("### \u{1F578}\uFE0F CKG Graph (confidence-ranked)");for(const t of y){const i=Math.round(t.edge.confidence*100),f="\u2593".repeat(Math.round(i/10))+"\u2591".repeat(10-Math.round(i/10));s.push(` ${t.edge.from} **\u2192[${t.edge.edgeType}]\u2192** ${t.edge.to}`),s.push(` ${f} ${i}% confidence (${t.edge.successes}/${t.edge.trials} confirmed)`),t.lesson?.what_worked&&s.push(` \u2705 Fix: ${t.lesson.what_worked.slice(0,150)}`),s.push("")}}if(k.length>0){s.push(y.length>0?`### \u{1F4DA} Text Search (${k.length} related lessons)`:`Found **${k.length}** related lessons. Reconstructed causal chain:`,"");const t=k.filter(n=>n.lesson.outcome!=="success"),i=k.filter(n=>n.lesson.outcome==="success");t.length>0&&(s.push("**Root causes & failure chain:**"),t.forEach((n,a)=>{const e=n.lesson,o=_[e.severity??"minor"]??"\u{1F7E1}";s.push(`${a===0?" Root:":" \u2192 :"} ${o} \`${e.topic}\``),e.what_failed&&s.push(` \u21B3 ${e.what_failed.slice(0,120)}`)}),s.push("")),i.length>0&&(s.push("**Solutions that worked before:**"),i.forEach((n,a)=>{const e=n.lesson,o=new Date(e.ts).toLocaleDateString("de-DE");s.push(` ${a+1}. \u2705 \`${e.topic}\` \u2014 ${o} \xB7 recalled ${e.recall_count??0}\xD7`),e.what_worked&&s.push(` ${e.what_worked.slice(0,200)}`)}),s.push(""));const f=i[0]?.lesson;if(f?.what_worked){s.push("**\u26A1 Most likely fix:**"),s.push("```"),s.push(f.what_worked.slice(0,500)),s.push("```"),s.push("");const n=O(f)?K(f,"trace"):0;n>0&&d.incrbyfloat(`cachly:stats:time_saved_mins:${l}`,n).catch(()=>{})}}return s.push(`\u{1F4A1} After applying: \`learn_from_attempts(topic="fix:${u[0]??"issue"}", outcome="success", ...)\``),y.length>0&&s.push(`\u{1F578}\uFE0F Explore graph: \`ckg_inspect(concept="${u[0]??"fix"}")\``),s.join(`
7
- `)}case"knowledge_decay":{let y=function(s){const t=Math.round(s/10);return"\u2588".repeat(t)+"\u2591".repeat(10-t)+` ${s}%`};const{instance_id:l,min_age_days:p=0,show_top:$=20}=A,m=await M(l),g=Date.now(),d=p*864e5;let u=0;const _=[];do{const[s,t]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(s),_.push(...t)}while(u!==0);const c=[];for(const s of _){const t=await m.get(s);if(t){const i=x(t,null);if(!i)continue;const f=g-new Date(i.ts).getTime();if(f<d)continue;const n=Math.floor(f/864e5),a=i.recall_count??0,e=Math.max(0,n-7),o=Math.max(5,100-e),r=Math.min(50,a*5),D=i.outcome==="failure"?-20:0,T=Math.min(100,Math.max(0,o+r+D));c.push({topic:i.topic,confidence:T,age_days:n,recalls:a,outcome:i.outcome})}}c.sort((s,t)=>s.confidence-t.confidence);const w=c.slice(0,$),b=c.length>0?Math.round(c.reduce((s,t)=>s+t.confidence,0)/c.length):0,v=c.filter(s=>s.confidence<30).length,h=c.filter(s=>s.confidence>=70).length;return[`\u{1F9EA} **Knowledge Decay Report** \u2014 ${c.length} lessons`,"",`Average confidence: **${y(b)}**`,`\u{1F534} Critical (<30%): ${v} \u{1F7E2} Healthy (\u226570%): ${h}`,"","Lowest confidence lessons (fix these first):","",...w.map((s,t)=>`${(t+1).toString().padStart(2)}. \`${s.topic}\`
8
- ${y(s.confidence)} \xB7 ${s.age_days}d old \xB7 ${s.recalls} recalls \xB7 ${s.outcome}`),"",c.length>$?`\u2026 and ${c.length-$} more lessons`:"","",v>0?`\u26A0\uFE0F ${v} lessons are critically stale. Validate them and re-run \`learn_from_attempts\` with updated findings.`:"\u2705 Brain confidence is healthy overall.","","\u{1F4A1} Run `memory_consolidate` to prune stale entries \xB7 `causal_trace` to find root causes."].filter(s=>s!=="").join(`
9
- `)}case"autopilot":{const{instance_id:l,editor:p="claude",project_name:$="this project",style:m="full"}=A,g=U({editor:String(p),project_name:String($)},"die Anweisungsdatei (CLAUDE.md)");if(!g.ok)return g.meldung;const d=(v,h)=>v.replace(/[\p{C}\s]+/gu," ").trim().slice(0,h),u=d(g.felder.editor,30)||"claude",_=d(g.felder.project_name,80)||"this project",c=`## Cachly AI Brain \u2014 Autopilot
5
+ No matching lessons found in brain.`);if(w)return w;const d=await M(l),u=g.toLowerCase().replace(/[^a-z0-9\s\-_:]/g," ").split(/\s+/).filter(o=>o.length>2),_={critical:"\u{1F534}",major:"\u{1F7E0}",minor:"\u{1F7E1}"},c=[];try{for(const o of u.slice(0,4)){const a=await d.smembers(`cachly:ckg:idx:from:${j(o)}`),r=await d.smembers(`cachly:ckg:idx:to:${j(o)}`),p=[],n=d.scanStream({match:`cachly:ckg:node:*${o}*`,count:50});await new Promise((e,s)=>{n.on("data",i=>p.push(...i)),n.on("end",e),n.on("error",s)});for(const e of p.slice(0,10)){const s=await d.get(e);if(!s)continue;const i=x(s,null);if(!i)continue;const D=await d.smembers(`cachly:ckg:idx:from:${i.id}`);for(const T of D.slice(0,20)){const R=await d.get(T);if(!R)continue;const C=x(R,null);if(!C||C.edgeType!=="fixes"&&C.edgeType!=="requires")continue;const I=await d.get(`cachly:lesson:best:${C.from.replace(/-/g,":").replace(/^fix:/,"fix:")}`),E=I?x(I,null)??void 0:void 0;c.push({conceptId:i.id,edge:C,lesson:E&&B(E)?E:void 0})}}for(const e of[...a,...r].slice(0,20)){const s=await d.get(e);if(!s)continue;const i=x(s,null);if(!i)continue;const D=await d.get(`cachly:lesson:best:${i.from}`),T=D?x(D,null)??void 0:void 0;c.push({conceptId:i.from,edge:i,lesson:T&&B(T)?T:void 0})}}}catch{}const y=new Set,f=c.filter(o=>{const a=`${o.edge.from}:${o.edge.edgeType}:${o.edge.to}`;return y.has(a)?!1:(y.add(a),!0)}).sort((o,a)=>a.edge.confidence-o.edge.confidence).slice(0,$);let k=0;const b=[];do{const[o,a]=await d.scan(k,"MATCH","cachly:lesson:*","COUNT",200);k=parseInt(o),b.push(...a)}while(k!==0);const h=[];for(const o of b){const a=await d.get(o);if(a){const r=x(a,null);if(!r||!B(r)||m.length>0&&!(r.tags??[]).some(e=>m.includes(e)))continue;const p=[r.topic,r.what_failed??"",r.what_worked??"",r.context??""].join(" ").toLowerCase(),n=u.reduce((e,s)=>e+(p.includes(s)?1:0),0);n>0&&h.push({score:n,lesson:r,key:o})}}h.sort((o,a)=>a.score-o.score);const v=h.slice(0,$);if(v.length===0&&f.length===0)return[`\u{1F50D} **Causal Trace: "${g}"**`,"","No matching lessons found in brain.","","\u{1F4A1} After you solve this, call:","```","learn_from_attempts(",` instance_id = "${l}",`,` topic = "fix:${u[0]??"issue"}",`,' outcome = "success",',' what_worked = "...",',` what_failed = "${g}",`,")","```"].join(`
6
+ `);const t=[`\u{1F50D} **Causal Trace: "${g}"**`,""];if(f.length>0){t.push("### \u{1F578}\uFE0F CKG Graph (confidence-ranked)");for(const o of f){const a=Math.round(o.edge.confidence*100),r="\u2593".repeat(Math.round(a/10))+"\u2591".repeat(10-Math.round(a/10));t.push(` ${o.edge.from} **\u2192[${o.edge.edgeType}]\u2192** ${o.edge.to}`),t.push(` ${r} ${a}% confidence (${o.edge.successes}/${o.edge.trials} confirmed)`),o.lesson?.what_worked&&t.push(` \u2705 Fix: ${o.lesson.what_worked.slice(0,150)}`),t.push("")}}if(v.length>0){t.push(f.length>0?`### \u{1F4DA} Text Search (${v.length} related lessons)`:`Found **${v.length}** related lessons. Reconstructed causal chain:`,"");const o=v.filter(p=>p.lesson.outcome!=="success"),a=v.filter(p=>p.lesson.outcome==="success");o.length>0&&(t.push("**Root causes & failure chain:**"),o.forEach((p,n)=>{const e=p.lesson,s=_[e.severity??"minor"]??"\u{1F7E1}";t.push(`${n===0?" Root:":" \u2192 :"} ${s} \`${e.topic}\``),e.what_failed&&t.push(` \u21B3 ${e.what_failed.slice(0,120)}`)}),t.push("")),a.length>0&&(t.push("**Solutions that worked before:**"),a.forEach((p,n)=>{const e=p.lesson,s=new Date(e.ts).toLocaleDateString("de-DE");t.push(` ${n+1}. \u2705 \`${e.topic}\` \u2014 ${s} \xB7 recalled ${e.recall_count??0}\xD7`),e.what_worked&&t.push(` ${e.what_worked.slice(0,200)}`)}),t.push(""));const r=a[0]?.lesson;if(r?.what_worked){t.push("**\u26A1 Most likely fix:**"),t.push("```"),t.push(r.what_worked.slice(0,500)),t.push("```"),t.push("");const p=F(r)?P(r,"trace"):0;p>0&&d.incrbyfloat(`cachly:stats:time_saved_mins:${l}`,p).catch(()=>{})}}return t.push(`\u{1F4A1} After applying: \`learn_from_attempts(topic="fix:${u[0]??"issue"}", outcome="success", ...)\``),f.length>0&&t.push(`\u{1F578}\uFE0F Explore graph: \`ckg_inspect(concept="${u[0]??"fix"}")\``),t.join(`
7
+ `)}case"knowledge_decay":{let f=function(t){const o=Math.round(t/10);return"\u2588".repeat(o)+"\u2591".repeat(10-o)+` ${t}%`};const{instance_id:l,min_age_days:g=0,show_top:$=20}=S,m=await M(l),w=Date.now(),d=g*864e5;let u=0;const _=[];do{const[t,o]=await m.scan(u,"MATCH","cachly:lesson:best:*","COUNT",200);u=parseInt(t),_.push(...o)}while(u!==0);const c=[];for(const t of _){const o=await m.get(t);if(o){const a=x(o,null);if(!a)continue;const r=w-new Date(a.ts).getTime();if(r<d)continue;const p=Math.floor(r/864e5),n=a.recall_count??0,e=Math.max(0,p-7),s=Math.max(5,100-e),i=Math.min(50,n*5),D=a.outcome==="failure"?-20:0,T=Math.min(100,Math.max(0,s+i+D));c.push({topic:a.topic,confidence:T,age_days:p,recalls:n,outcome:a.outcome})}}c.sort((t,o)=>t.confidence-o.confidence);const y=c.slice(0,$),k=c.length>0?Math.round(c.reduce((t,o)=>t+o.confidence,0)/c.length):0,b=c.filter(t=>t.confidence<30).length,h=c.filter(t=>t.confidence>=70).length;return[`\u{1F9EA} **Knowledge Decay Report** \u2014 ${c.length} lessons`,"",`Average confidence: **${f(k)}**`,`\u{1F534} Critical (<30%): ${b} \u{1F7E2} Healthy (\u226570%): ${h}`,"","Lowest confidence lessons (fix these first):","",...y.map((t,o)=>`${(o+1).toString().padStart(2)}. \`${t.topic}\`
8
+ ${f(t.confidence)} \xB7 ${t.age_days}d old \xB7 ${t.recalls} recalls \xB7 ${t.outcome}`),"",c.length>$?`\u2026 and ${c.length-$} more lessons`:"","",b>0?`\u26A0\uFE0F ${b} lessons are critically stale. Validate them and re-run \`learn_from_attempts\` with updated findings.`:"\u2705 Brain confidence is healthy overall.","","\u{1F4A1} Run `memory_consolidate` to prune stale entries \xB7 `causal_trace` to find root causes."].filter(t=>t!=="").join(`
9
+ `)}case"autopilot":{const{instance_id:l,editor:g="claude",project_name:$="this project",style:m="full"}=S,w=z({editor:String(g),project_name:String($)},"die Anweisungsdatei (CLAUDE.md)");if(!w.ok)return w.meldung;const d=(b,h)=>b.replace(/[\p{C}\s]+/gu," ").trim().slice(0,h),u=d(w.felder.editor,30)||"claude",_=d(w.felder.project_name,80)||"this project",c=`## Cachly AI Brain \u2014 Autopilot
10
10
 
11
11
  **Instance:** \`${l}\`
12
12
 
@@ -22,7 +22,7 @@ No matching lessons found in brain.`);if(g)return g;const d=await M(l),u=p.toLow
22
22
  - **Window opens** \u2192 call \`session_start(instance_id="${l}", focus="<today's goal>")\`
23
23
  - **Bug fixed / deployed / discovered** \u2192 call \`learn_from_attempts(instance_id="${l}", topic="fix:<area>", outcome="success", what_worked="...")\`
24
24
  - **Window closes** \u2192 call \`session_end(instance_id="${l}", summary="...", files_changed=[...])\`
25
- `,w=`## Cachly AI Brain \u2014 Autopilot for ${_}
25
+ `,y=`## Cachly AI Brain \u2014 Autopilot for ${_}
26
26
 
27
27
  **Instance:** \`${l}\`
28
28
 
@@ -101,5 +101,5 @@ smart_recall(
101
101
  ---
102
102
 
103
103
  *Cachly v0.6 \xB7 Generated ${new Date().toISOString().slice(0,10)}*
104
- `,y=m==="minimal"?c:w,b=u==="copilot"?".github/copilot-instructions.md":u==="continue"?".continue/cachly-autopilot.md":"CLAUDE.md";return[`\u{1F916} **Autopilot instructions generated** for **${u==="all"?"all editors":u}**`,"",`**File:** \`${b}\` \u2014 create it, or APPEND to your existing one`,"","```markdown",y,"```","",`**How to apply** (\`>>\` appends \u2014 an existing ${b} keeps every line you wrote):`,"```bash",`cat >> ${b} << 'EOF'`,y,"EOF","```","",`\u2728 Once this file is in place, **${u==="copilot"?"GitHub Copilot":u==="continue"?"Continue.dev":"Claude/Cursor/Windsurf"}** will manage the Brain automatically \u2014 no manual calls needed, ever.`].join(`
105
- `)}default:return null}}export{J as ADVANCED_TOOL_NAMES,Y as handleAdvancedTool};
104
+ `,f=m==="minimal"?c:y,k=u==="copilot"?".github/copilot-instructions.md":u==="continue"?".continue/cachly-autopilot.md":"CLAUDE.md";return[`\u{1F916} **Autopilot instructions generated** for **${u==="all"?"all editors":u}**`,"",`**File:** \`${k}\` \u2014 create it, or APPEND to your existing one`,"","```markdown",f,"```","",`**How to apply** (\`>>\` appends \u2014 an existing ${k} keeps every line you wrote):`,"```bash",`cat >> ${k} << 'EOF'`,f,"EOF","```","",`\u2728 Once this file is in place, **${u==="copilot"?"GitHub Copilot":u==="continue"?"Continue.dev":"Claude/Cursor/Windsurf"}** will manage the Brain automatically \u2014 no manual calls needed, ever.`].join(`
105
+ `)}default:return null}}export{te as ADVANCED_TOOL_NAMES,ne as handleAdvancedTool};