@cachly-dev/mcp-server 0.10.188 → 0.10.191

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 CHANGED
@@ -444,6 +444,9 @@ The free tier needs no credit card.
444
444
  | `CACHLY_PROFILE` | unset | `lean` lists 8 tools plus `cachly_tool`, `recall` lists the 3 read-only tools |
445
445
  | `CACHLY_UPDATE_CHECK` | on | Set to `false` to stop the version check. npm is asked at most once a day, with a 2-second limit |
446
446
  | `CACHLY_NO_TELEMETRY` | unset | Set to `1` to disable usage pings. They include your API token and up to 80 characters of `smart_recall` queries |
447
+ | `CACHLY_LERNEN` | on | Learning from use in the prompt hook. For 5 % of prompts the matching lessons are computed but not shown (control group), up to 10 % try a stricter or shorter setting. At the end of each turn the hook reports which setting ran and whether the agent named a shown lesson; topics are sent hashed, prompts never. Set to `0` (or `CACHLY_NO_TELEMETRY=1`) to turn it off |
448
+ | `CACHLY_KONTROLLE_ANTEIL` | `5%` | Share of prompts in the control group. `0` turns the control group off, at most `50%` |
449
+ | `CACHLY_ERKUNDUNG` | `10%` | Share of prompts that may try another setting. `0` keeps the leading setting, at most `10%` |
447
450
 
448
451
  ## Ecosystem and docs
449
452
 
@@ -1,2 +1,2 @@
1
- import{promptEinblendung as c,holeBestand as u,sitzungsKontext as l,hookAusgabe as i,estimateTokens as a}from"./einblendung.js";function f(e){const t=(e??"").trim();if(!t)return null;try{const n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}const m=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function p(e){const t=e.hook_event_name??"UserPromptSubmit";if(t==="SessionStart"||t==="Stop")return null;if(t==="PreToolUse"){if(e.tool_name&&!m.has(e.tool_name))return null;const r=e.tool_input?.file_path;if(typeof r!="string"||!r.trim())return null;const o=r.trim().replace(/\\/g,"/"),s=(e.cwd??"").replace(/\\/g,"/").replace(/\/+$/,"");return s&&o.toLowerCase().startsWith(s.toLowerCase()+"/")?o.slice(s.length+1):o}return(e.prompt??"").trim()||null}const g=/\b(fixed|resolved|behoben|gefixt|root cause|the bug was|der fehler (lag|war)|ursache (war|gefunden)|now passes|tests? (are|is|sind) (green|grün)|deployed successfully)\b/i;function b(e){const t=(e.last_assistant_message??"").trim();return t.length<80||!g.test(t)?null:{action:(t.split(`
2
- `).find(r=>r.trim().length>0)?.trim()??t).slice(0,200),outcome:"success",details:t.slice(0,500),severity:"minor"}}function d(e){const t=e.action.toLowerCase().replace(/[^a-z0-9:\-_\s]/g,"").trim().split(/\s+/).slice(0,4).join("-");return{topic:t?t.includes(":")?t:`auto:${t}`:"auto:stop",outcome:e.outcome,what_worked:e.action,context:e.details,severity:e.severity,source:"ambient-stop",tags:["auto-learned"]}}const x=i,h=5e3;async function k(e,t){try{const n=f(e);if(!n)return"";const r=n.hook_event_name??"UserPromptSubmit";if(!t.cfg.jwt||!t.cfg.instanceId)return"";let o="";if(r==="SessionStart"){const{lessons:s}=await u(t.cfg,{force:!0,fetchFn:t.fetchFn});o=l(s)}else{const s=p(n);if(s===null)return"";o=(await c(s,t.cfg,{nebenlauf:t.nebenlauf,abrufMs:h,leser:r!=="PreToolUse",session:n.session_id??null,protokoll:t.protokoll,fetchFn:t.fetchFn})).kontext}if(!o)return"";try{t.onInject?.(a(o),r)}catch{}return i(r,o)}catch{return""}}export{h as PROMPT_ABRUF_MS,x as buildHookOutput,f as parseHookPayload,p as recallQueryFor,k as runEinblendung,d as stopLernanfrage,b as stopObservation};
1
+ import{promptEinblendung as c,holeBestand as u,sitzungsKontext as l,hookAusgabe as i,estimateTokens as a}from"./einblendung.js";function f(e){const t=(e??"").trim();if(!t)return null;try{const n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}const m=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function p(e){const t=e.hook_event_name??"UserPromptSubmit";if(t==="SessionStart"||t==="Stop")return null;if(t==="PreToolUse"){if(e.tool_name&&!m.has(e.tool_name))return null;const r=e.tool_input?.file_path;if(typeof r!="string"||!r.trim())return null;const o=r.trim().replace(/\\/g,"/"),s=(e.cwd??"").replace(/\\/g,"/").replace(/\/+$/,"");return s&&o.toLowerCase().startsWith(s.toLowerCase()+"/")?o.slice(s.length+1):o}return(e.prompt??"").trim()||null}const g=/\b(fixed|resolved|behoben|gefixt|root cause|the bug was|der fehler (lag|war)|ursache (war|gefunden)|now passes|tests? (are|is|sind) (green|grün)|deployed successfully)\b/i;function w(e){const t=(e.last_assistant_message??"").trim();return t.length<80||!g.test(t)?null:{action:(t.split(`
2
+ `).find(r=>r.trim().length>0)?.trim()??t).slice(0,200),outcome:"success",details:t.slice(0,500),severity:"minor"}}function b(e){const t=e.action.toLowerCase().replace(/[^a-z0-9:\-_\s]/g,"").trim().split(/\s+/).slice(0,4).join("-");return{topic:t?t.includes(":")?t:`auto:${t}`:"auto:stop",outcome:e.outcome,what_worked:e.action,context:e.details,severity:e.severity,source:"ambient-stop",tags:["auto-learned"]}}const x=i,h=5e3;async function k(e,t){try{const n=f(e);if(!n)return"";const r=n.hook_event_name??"UserPromptSubmit";if(!t.cfg.jwt||!t.cfg.instanceId)return"";let o="";if(r==="SessionStart"){const{lessons:s}=await u(t.cfg,{force:!0,fetchFn:t.fetchFn});o=l(s)}else{const s=p(n);if(s===null)return"";o=(await c(s,t.cfg,{nebenlauf:t.nebenlauf,abrufMs:h,leser:r!=="PreToolUse",session:n.session_id??null,protokoll:t.protokoll,ereignis:r,editor:t.editor,fetchFn:t.fetchFn})).kontext}if(!o)return"";try{t.onInject?.(a(o),r)}catch{}return i(r,o)}catch{return""}}export{h as PROMPT_ABRUF_MS,x as buildHookOutput,f as parseHookPayload,p as recallQueryFor,k as runEinblendung,b as stopLernanfrage,w as stopObservation};
@@ -1,2 +1,2 @@
1
- import{readFileSync as P}from"node:fs";import{parseHookPayload as g,runEinblendung as U,stopLernanfrage as k,stopObservation as y}from"./ambient-cli.js";import{stopAntwort as O}from"./schreibbeleg.js";import{holeBestand as I}from"./einblendung.js";import{appendLedgerEntry as T,reportLedgerEntry as E}from"./ambient-ledger.js";import{copilotHatHook as F,cursorHatHook as C,findeInstanz as S,findeSchluessel as _,hookUmfeld as h,projektHatHook as v}from"./hook-zugang.js";import{CURSOR_FLAG as l,cursorEreignis as w,cursorHookAntwort as R,cursorLeer as j,istCursorNutzlast as x}from"./cursor-hook.js";import{COPILOT_FLAG as b,copilotEreignis as N,copilotHookAntwort as G,istFremdeLaufzeit as z}from"./copilot-hook.js";import{CODEX_FLAG as B,codexHookAntwort as D}from"./codex-hook.js";import{GEMINI_FLAG as A,geminiEreignis as Y,geminiHookAntwort as K}from"./gemini-hook.js";const M="https://api.cachly.dev",$="ambient-auffrischen",H=new Set(["SessionStart","UserPromptSubmit","PreToolUse","Stop"]);async function J(t,e){if(!t.args.includes(l)&&(w(e,t.args)!=="sessionStart"||C(t.umfeld)))return"";const o=t.args.filter(n=>n==="--plugin");return R({payload:e,args:t.args,claudeLauf:(n,u)=>p({...t,raw:n,args:[u,...o]}),ablageOrdner:t.cursorAblage})}function V(t,e){const r=(o,n)=>p({...t,raw:o,args:[n]});return t.args.includes(b)?G({payload:e,args:t.args,claudeLauf:r,ablageOrdner:t.copilotAblage}):t.args.includes(B)?D({payload:e,args:t.args,claudeLauf:r}):t.args.includes(A)?K({payload:e,args:t.args,claudeLauf:r}):null}async function p(t){try{const e=g(t.raw);if(t.args.includes(l)||x(e))return await J(t,e);const r=V(t,e);if(r)return await r;const o=e?.hook_event_name??t.args.find(i=>H.has(i))??t.umfeld.env.CACHLY_HOOK_EVENT??"";if(z(e)&&(o!=="SessionStart"&&o!=="UserPromptSubmit"||F(t.umfeld))||t.args.includes("--plugin")&&o&&v(o,t.umfeld))return"";if(o==="Stop"&&e?.transcript_path)try{const i=P(e.transcript_path,"utf-8").split(`
2
- `),f=O(i,e.stop_hook_active===!0);if(f)return f}catch{}const n=_(t.umfeld),u=S(t.umfeld);if(!n||!u)return"";const c={apiUrl:t.apiUrl,jwt:n,instanceId:u};if(o==="Stop"){const i=e?y(e):null;return i&&await(t.fetchFn??fetch)(`${c.apiUrl}/api/v1/instances/${c.instanceId}/learn`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${c.jwt}`},body:JSON.stringify(k(i)),signal:AbortSignal.timeout(8e3)}).catch(()=>{}),""}let a;const s=await(t.einblenden??U)(t.raw,{cfg:c,nebenlauf:t.selbst?[t.selbst,$]:void 0,fetchFn:t.fetchFn,onInject:(i,f)=>{const m={ts:new Date().toISOString(),event:f,injected:i,prevented:0};T(m),a=E(c,m,t.fetchFn)}});return a&&await Promise.race([a,new Promise(i=>setTimeout(i,500))]),s}catch{return""}}async function X(){if(process.stdin.isTTY)return"";const t=[];for await(const e of process.stdin)t.push(e);return Buffer.concat(t).toString("utf-8")}function L(){return process.env.CACHLY_API_URL||M}const d={SessionStart:25e3,UserPromptSubmit:8e3,PreToolUse:8e3,Stop:5e4,sessionStart:25e3,beforeSubmitPrompt:8e3,postToolUse:3e3,userPromptSubmitted:8e3,PostToolUse:3e3,BeforeAgent:8e3};function q(t,e){return t.includes(l)?j(w(e,t)):t.includes(b)?N(e,t)?"{}":"":t.includes(A)&&Y(e,t)?"{}":""}async function ct(t,e){try{const r=await X(),o=g(r),n=o?.hook_event_name??t.find(s=>H.has(s)||Object.hasOwn(d,s))??"",u=Number(process.env.CACHLY_HOOK_FRIST_MS)||d[n]||d.UserPromptSubmit,c=q(t,o),a=await Promise.race([p({args:t,raw:r,umfeld:h(),apiUrl:L(),selbst:e}),new Promise(s=>setTimeout(()=>s(c),u))]);a&&await new Promise(s=>process.stdout.write(a,()=>s()))}catch{}process.exit(0)}async function ut(){try{const t=h(),e=_(t),r=S(t);e&&r&&await I({apiUrl:L(),jwt:e,instanceId:r},{force:!0})}catch{}process.exit(0)}export{$ as AUFFRISCHEN,d as HOOK_FRIST_MS,M as STANDARD_API_URL,ut as auffrischenHauptlauf,p as hookAntwort,ct as hookHauptlauf};
1
+ import{readFileSync as F}from"node:fs";import{parseHookPayload as _,runEinblendung as I,stopLernanfrage as T,stopObservation as E}from"./ambient-cli.js";import{stopAntwort as v}from"./schreibbeleg.js";import{holeBestand as C}from"./einblendung.js";import{belohnungMelden as x}from"./lernen.js";import{appendLedgerEntry as R,reportLedgerEntry as j}from"./ambient-ledger.js";import{copilotHatHook as N,cursorHatHook as G,findeInstanz as w,findeSchluessel as b,hookUmfeld as A,projektHatHook as z}from"./hook-zugang.js";import{CURSOR_FLAG as f,cursorEreignis as H,cursorHookAntwort as B,cursorLeer as D,istCursorNutzlast as P}from"./cursor-hook.js";import{COPILOT_FLAG as m,copilotEreignis as M,copilotHookAntwort as Y,istFremdeLaufzeit as L}from"./copilot-hook.js";import{CODEX_FLAG as U,codexHookAntwort as K}from"./codex-hook.js";import{GEMINI_FLAG as g,geminiEreignis as $,geminiHookAntwort as V}from"./gemini-hook.js";const J="https://api.cachly.dev",X="ambient-auffrischen",k=new Set(["SessionStart","UserPromptSubmit","PreToolUse","Stop"]);async function q(t,e){if(!t.args.includes(f)&&(H(e,t.args)!=="sessionStart"||G(t.umfeld)))return"";const s=t.args.filter(n=>n==="--plugin");return B({payload:e,args:t.args,claudeLauf:(n,c)=>S({...t,raw:n,args:[c,...s]}),ablageOrdner:t.cursorAblage})}function Q(t,e){const r=(s,n)=>S({...t,raw:s,args:[n]});return t.args.includes(m)?Y({payload:e,args:t.args,claudeLauf:r,ablageOrdner:t.copilotAblage}):t.args.includes(U)?K({payload:e,args:t.args,claudeLauf:r}):t.args.includes(g)?V({payload:e,args:t.args,claudeLauf:r}):null}function W(t,e){return t.includes(f)||P(e)?"cursor":t.includes(m)?"copilot":t.includes(U)?"codex":t.includes(g)?"gemini":L(e)?"vscode":"claude"}async function S(t){try{const e=_(t.raw),r={...t,editor:t.editor??W(t.args,e)};if(r.args.includes(f)||P(e))return await q(r,e);const s=Q(r,e);if(s)return await s;const n=e?.hook_event_name??r.args.find(i=>k.has(i))??r.umfeld.env.CACHLY_HOOK_EVENT??"";if(L(e)&&(n!=="SessionStart"&&n!=="UserPromptSubmit"||N(r.umfeld))||r.args.includes("--plugin")&&n&&z(n,r.umfeld))return"";let c=null;if(n==="Stop"&&e?.transcript_path)try{c=F(e.transcript_path,"utf-8").split(`
2
+ `);const i=v(c,e.stop_hook_active===!0);if(i)return i}catch{}const a=b(r.umfeld),u=w(r.umfeld);if(!a||!u)return"";const o={apiUrl:r.apiUrl,jwt:a,instanceId:u};if(n==="Stop"){const i=e?E(e):null,d=i?(r.fetchFn??fetch)(`${o.apiUrl}/api/v1/instances/${o.instanceId}/learn`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o.jwt}`},body:JSON.stringify(T(i)),signal:AbortSignal.timeout(8e3)}).catch(()=>{}):void 0,l=x(o,e?.session_id??null,c,{fetchFn:r.fetchFn});return await Promise.all([d,l]),""}let p;const y=await(r.einblenden??I)(r.raw,{cfg:o,nebenlauf:r.selbst?[r.selbst,X]:void 0,editor:r.editor,fetchFn:r.fetchFn,onInject:(i,d)=>{const l={ts:new Date().toISOString(),event:d,injected:i,prevented:0};R(l),p=j(o,l,r.fetchFn)}});return p&&await Promise.race([p,new Promise(i=>setTimeout(i,500))]),y}catch{return""}}async function Z(){if(process.stdin.isTTY)return"";const t=[];for await(const e of process.stdin)t.push(e);return Buffer.concat(t).toString("utf-8")}function O(){return process.env.CACHLY_API_URL||J}const h={SessionStart:25e3,UserPromptSubmit:8e3,PreToolUse:8e3,Stop:5e4,sessionStart:25e3,beforeSubmitPrompt:8e3,postToolUse:3e3,userPromptSubmitted:8e3,PostToolUse:3e3,BeforeAgent:8e3};function tt(t,e){return t.includes(f)?D(H(e,t)):t.includes(m)?M(e,t)?"{}":"":t.includes(g)&&$(e,t)?"{}":""}async function pt(t,e){try{const r=await Z(),s=_(r),n=s?.hook_event_name??t.find(o=>k.has(o)||Object.hasOwn(h,o))??"",c=Number(process.env.CACHLY_HOOK_FRIST_MS)||h[n]||h.UserPromptSubmit,a=tt(t,s),u=await Promise.race([S({args:t,raw:r,umfeld:A(),apiUrl:O(),selbst:e}),new Promise(o=>setTimeout(()=>o(a),c))]);u&&await new Promise(o=>process.stdout.write(u,()=>o()))}catch{}process.exit(0)}async function dt(){try{const t=A(),e=b(t),r=w(t);e&&r&&await C({apiUrl:O(),jwt:e,instanceId:r},{force:!0,lernen:!0})}catch{}process.exit(0)}export{X as AUFFRISCHEN,h as HOOK_FRIST_MS,J as STANDARD_API_URL,dt as auffrischenHauptlauf,W as editorVon,S as hookAntwort,pt as hookHauptlauf};
@@ -1 +1 @@
1
- import{Seltenheit as p,inhaltsWoerter as l,grobStamm as f,spreizeImTopf as d}from"./rangfolge.js";import{lektionsText as w}from"./seltenheitsbestand.js";import{bestandAusDokumenten as g,keywordSearchMitBestand as k}from"./search.js";import{SINN_TOPF as E,EINBLENDUNG_DECKUNG as b,EINBLENDUNG_ZEUGE as N}from"./rangfolge-stellschrauben.js";import{rahmeEin as G,entschaerfe as L,RAHMEN_ETIKETT as U,RAHMEN_HINWEIS as j}from"./einblendung-rahmen.js";import{stopAntwort as P}from"./schreibbeleg.js";const S=E,x=["topic","outcome","what_worked","what_failed","severity","confidence","recall_count","ts","endorsements"],m=new Set("the a an and or but for to of in on at is are be do does did we you i it this that with without how what why when where can could would should please just get set use using make made need bitte und oder der die das ein eine f\xFCr mit ohne wie was warum kann soll noch mal auch von den dem ist weil wenn dann doch aber alle jede jeder jedes immer wieder wird werden wurde muss beim sehr nicht".split(/\s+/)),_=["ierungen","ierung","ieren","iert","ungen","ung","heit","keit","lich","isch","ing","ed","en","er","es","e","n","s"];function T(o){for(const e of _)if(o.length-e.length>=4&&o.endsWith(e))return o.slice(0,-e.length);return o}function z(o){return[...new Set(String(o).toLowerCase().split(/[^a-z0-9]+/).filter(e=>e.length>3&&!m.has(e)).map(T).filter(e=>!m.has(e)))]}function y(o,e){let i=0;for(const s of o)e.includes(s)&&i++;return i}class O{lektionen;texte;wortmengen;heuhaufen;statistik;wortbestand;platzVonSchluessel=new Map;topf;constructor(e,{topf:i=S}={}){this.lektionen=e,this.topf=i,this.texte=e.map(t=>w(t)),this.wortmengen=this.texte.map(t=>new Set([...l(t)].map(f))),this.heuhaufen=this.texte.map(t=>t.toLowerCase()),this.statistik=new p(this.texte);const s=e.map((t,h)=>{const u=`cachly:lesson:best:${String(t.topic??h)}`;this.platzVonSchluessel.set(u,h);const c={};for(const a of x)t[a]!==void 0&&(c[a]=t[a]);return{key:u,content:JSON.stringify(c)}});this.wortbestand=g(s)}get groesse(){return this.lektionen.length}sortiere(e){if(!this.wortbestand)return[];const i=k(this.wortbestand,e,this.topf),s=[],t=[];for(const n of i){const r=this.platzVonSchluessel.get(n.key);r!==void 0&&(s.push(r),t.push(n.score))}if(s.length===0)return[];const h=l(e),u=z(e),c=d(t),a=d(s.map(n=>this.statistik.besterZeuge(h,this.wortmengen[n])));return s.map((n,r)=>({lektion:this.lektionen[n],punkte:c[r]+b*this.statistik.deckung(h,this.wortmengen[n])+N*a[r],belege:y(u,this.heuhaufen[n])})).sort((n,r)=>r.punkte-n.punkte||Number(r.lektion.recall_count??0)-Number(n.lektion.recall_count??0))}}export{O as Einblendbestand,x as INDEX_FELDER,U as RAHMEN_ETIKETT,j as RAHMEN_HINWEIS,S as WORT_TOPF,L as entschaerfe,G as rahmeEin,T as stammKuerzen,P as stopAntwort,z as torWoerter,y as zaehleBelege};
1
+ import{Seltenheit as f,inhaltsWoerter as c,grobStamm as p,spreizeImTopf as d}from"./rangfolge.js";import{lektionsText as w}from"./seltenheitsbestand.js";import{bestandAusDokumenten as g,keywordSearchMitBestand as k}from"./search.js";import{SINN_TOPF as E,EINBLENDUNG_DECKUNG as b,EINBLENDUNG_ZEUGE as N}from"./rangfolge-stellschrauben.js";import{istMarkiert as S}from"./verdacht-marke.js";import{rahmeEin as U,entschaerfe as j,RAHMEN_ETIKETT as B,RAHMEN_HINWEIS as P}from"./einblendung-rahmen.js";import{stopAntwort as F}from"./schreibbeleg.js";const x=E,_=["topic","outcome","what_worked","what_failed","severity","confidence","recall_count","ts","endorsements"],m=new Set("the a an and or but for to of in on at is are be do does did we you i it this that with without how what why when where can could would should please just get set use using make made need bitte und oder der die das ein eine f\xFCr mit ohne wie was warum kann soll noch mal auch von den dem ist weil wenn dann doch aber alle jede jeder jedes immer wieder wird werden wurde muss beim sehr nicht".split(/\s+/)),T=["ierungen","ierung","ieren","iert","ungen","ung","heit","keit","lich","isch","ing","ed","en","er","es","e","n","s"];function z(s){for(const e of T)if(s.length-e.length>=4&&s.endsWith(e))return s.slice(0,-e.length);return s}function y(s){return[...new Set(String(s).toLowerCase().split(/[^a-z0-9]+/).filter(e=>e.length>3&&!m.has(e)).map(z).filter(e=>!m.has(e)))]}function I(s,e){let i=0;for(const o of s)e.includes(o)&&i++;return i}class A{texte;wortmengen;heuhaufen;statistik;wortbestand;platzVonSchluessel=new Map;topf;lektionen;constructor(e,{topf:i=x}={}){const o=e.filter(n=>!S(n));this.lektionen=o,this.topf=i,this.texte=o.map(n=>w(n)),this.wortmengen=this.texte.map(n=>new Set([...c(n)].map(p))),this.heuhaufen=this.texte.map(n=>n.toLowerCase()),this.statistik=new f(this.texte);const h=o.map((n,a)=>{const l=`cachly:lesson:best:${String(n.topic??a)}`;this.platzVonSchluessel.set(l,a);const u={};for(const t of _)n[t]!==void 0&&(u[t]=n[t]);return{key:l,content:JSON.stringify(u)}});this.wortbestand=g(h)}get groesse(){return this.lektionen.length}sortiere(e){if(!this.wortbestand)return[];const i=k(this.wortbestand,e,this.topf),o=[],h=[];for(const t of i){const r=this.platzVonSchluessel.get(t.key);r!==void 0&&(o.push(r),h.push(t.score))}if(o.length===0)return[];const n=c(e),a=y(e),l=d(h),u=d(o.map(t=>this.statistik.besterZeuge(n,this.wortmengen[t])));return o.map((t,r)=>({lektion:this.lektionen[t],punkte:l[r]+b*this.statistik.deckung(n,this.wortmengen[t])+N*u[r],belege:I(a,this.heuhaufen[t])})).sort((t,r)=>r.punkte-t.punkte||Number(r.lektion.recall_count??0)-Number(t.lektion.recall_count??0))}}export{A as Einblendbestand,_ as INDEX_FELDER,B as RAHMEN_ETIKETT,P as RAHMEN_HINWEIS,x as WORT_TOPF,j as entschaerfe,U as rahmeEin,z as stammKuerzen,F as stopAntwort,y as torWoerter,I as zaehleBelege};
@@ -1,8 +1,8 @@
1
- import{readFileSync as I,existsSync as v,writeFileSync as b,mkdirSync as D,statSync as Y,appendFileSync as J}from"node:fs";import{dirname as k,join as h}from"node:path";import{tmpdir as m}from"node:os";import{createHash as q}from"node:crypto";import{spawn as Z}from"node:child_process";import{Einblendbestand as x,torWoerter as L}from"./einblendung-kern.js";import{rahmeEin as N}from"./einblendung-rahmen.js";import{leserText as z}from"./seltenheitsbestand.js";import{mischeMitLeser as C}from"./leser.js";import{LeserSicherung as F,dateiSpeicher as G,frageLeser as K}from"./leser-sicherung.js";import{LESER_TIEFE_EINBLENDUNG as W,LESER_ZEITLIMIT_MS as V}from"./rangfolge-stellschrauben.js";import{stufeEinblendungNachVersion as X}from"./gueltigkeit-version.js";export*from"./einblendung-kern.js";const Q=600*1e3,T=8e3,ee=60*1e3,j=120,$=W,te=1500,R=V,ne=h(m(),"cachly-ambient-netlog.jsonl");function be(e=process.cwd()){const t={apiUrl:process.env.CACHLY_API_URL||"https://api.cachly.dev",jwt:process.env.CACHLY_JWT||"",instanceId:process.env.CACHLY_BRAIN_INSTANCE_ID||""};if(t.jwt&&t.instanceId)return t;let n=e;for(let o=0;o<8;o++){const r=h(n,".mcp.json");if(v(r))try{const i=JSON.parse(I(r,"utf8"))?.mcpServers?.cachly?.env??{};if(t.apiUrl=t.apiUrl||i.CACHLY_API_URL||"https://api.cachly.dev",t.jwt=t.jwt||i.CACHLY_JWT||"",t.instanceId=t.instanceId||i.CACHLY_BRAIN_INSTANCE_ID||"",t.jwt&&t.instanceId)return t}catch{}const s=k(n);if(s===n)break;n=s}return t}function S(e){return q("sha1").update(e).digest("hex").slice(0,12)}function re(e){return h(m(),`cachly-ambient-bestand-${S(e)}.json`)}function se(e){return h(m(),`cachly-leser-sicherung-${S(e)}.json`)}function oe(e){return h(m(),`cachly-ambient-auffrischen-${S(e)}.lock`)}async function M(e,{fetchFn:t=fetch,zeitlimitMs:n=T}={}){try{const o=await t(`${e.apiUrl}/api/v1/instances/${e.instanceId}/export`,{headers:{Authorization:`Bearer ${e.jwt}`},signal:AbortSignal.timeout(n)});if(!o.ok)return null;const r=await o.json();return Array.isArray(r?.lessons)?r.lessons.map(s=>typeof s=="string"?ie(s):s).filter(s=>!!s&&typeof s=="object"):null}catch{return null}}function ie(e){try{return JSON.parse(e)}catch{return null}}function H(e,t){try{D(k(e),{recursive:!0}),b(e,JSON.stringify({at:Date.now(),lessons:t}),{mode:384})}catch{}}function O(e){try{const t=JSON.parse(I(e,"utf8"));if(Array.isArray(t?.lessons))return{at:Number(t.at)||0,lessons:t.lessons}}catch{}return null}function ae(e,t){const n=oe(e.instanceId);try{if(v(n)&&Date.now()-Y(n).mtimeMs<ee)return;b(n,String(Date.now()),{mode:384})}catch{return}try{Z(process.execPath,t,{detached:!0,stdio:"ignore",env:{...process.env,CACHLY_API_URL:e.apiUrl,CACHLY_JWT:e.jwt,CACHLY_BRAIN_INSTANCE_ID:e.instanceId}}).unref()}catch{}}async function ce(e,{force:t=!1,nebenlauf:n,abrufMs:o=T,fetchFn:r}={}){if(!e.jwt||!e.instanceId)return{lessons:[],quelle:"nicht-eingerichtet"};const s=re(e.instanceId);if(t){const c=await M(e,{fetchFn:r,zeitlimitMs:o});if(c)return H(s,c),{lessons:c,quelle:"server"};const l=O(s);return l?{lessons:l.lessons,quelle:"platte-alt"}:{lessons:[],quelle:"server-nicht-erreichbar"}}const i=O(s);if(i){const c=Date.now()-i.at<Q;return!c&&n&&ae(e,n),{lessons:i.lessons,quelle:c?"platte":"platte-alt"}}const u=await M(e,{fetchFn:r,zeitlimitMs:o});return u?(H(s,u),{lessons:u,quelle:"server"}):{lessons:[],quelle:"server-nicht-erreichbar"}}function g(e){return Math.ceil(String(e).length/4)}function E(e){const t=e.severity?`[${e.severity}] `:"",n=String(e.what_worked??"").replace(/\s+/g," ").trim(),o=n.length>j?`${n.slice(0,j)}\u2026`:n,r=typeof e.versionshinweis=="string"?` [${e.versionshinweis}]`:"";return`- ${t}${e.topic}${r}: ${o}`}const d={lessons:[],tokens:0,topScore:0,belege:0};function U(e,t,n){const o=[];let r=0;e=X(e);for(const{lektion:s}of e.slice(0,t)){const i=g(E(s));if(r+i>n)break;o.push(s),r+=i}return{lessons:o,tokens:r,topScore:Math.round(e[0].punkte*100)/100,belege:e[0].belege}}function ke(e,t,{minBelege:n=2,topK:o=3,tokenBudget:r=600}={}){if(!Array.isArray(t)||t.length===0)return{...d};if(L(e).length===0)return{...d};const s=new x(t).sortiere(e).filter(i=>i.belege>=n);return s.length===0?{...d}:U(s,o,r)}function le(e){return z(e,te)}async function B(e,t,n,{zeitlimitMs:o=R,fetchFn:r}={}){if(!e?.jwt||!e?.instanceId||n.length===0)return{art:"ohne"};if(["0","off","aus","false"].includes(String(process.env.CACHLY_LESER||"").toLowerCase()))return{art:"ohne"};const s=new F(G(se(e.instanceId)));return K({url:`${e.apiUrl}/api/v1/rerank`,jwt:e.jwt,frage:t,texte:n,instanceId:e.instanceId,zeitlimitMs:o,fetchFn:r},s)}async function xe(e,t,n,o={}){const r=await B(e,t,n,o);return r.art==="punkte"?{scores:r.scores,provider:r.provider,ms:r.ms}:null}async function ue(e,t,n,{minBelege:o=2,topK:r=3,tokenBudget:s=600,tiefe:i=$,zeitlimitMs:u=R,fetchFn:c}={}){const l={...d,leser:"aus",leserMs:0};if(!Array.isArray(t)||t.length===0||L(e).length===0)return l;let a=new x(t).sortiere(e).filter(p=>p.belege>=o);if(a.length===0)return l;let y="aus",w=0;if(a.length>1&&i>0){const p=a.slice(0,i),P=a.slice(i),f=await B(n,e,p.map(A=>le(A.lektion)),{zeitlimitMs:u,fetchFn:c});f.art==="punkte"?(a=[...C(p.map(_=>_.punkte),f.scores,1).map(_=>p[_]),...P],y=f.provider,w=f.ms):f.art==="uebersprungen"&&(y="uebersprungen")}return{...U(a,r,s),leser:y,leserMs:w}}function pe(e){if(!e.lessons.length)return"";const t=e.lessons.map(E).join(`
1
+ import{readFileSync as L,existsSync as M,writeFileSync as x,mkdirSync as K,statSync as q,appendFileSync as F}from"node:fs";import{dirname as C,join as S}from"node:path";import{tmpdir as k}from"node:os";import{createHash as G}from"node:crypto";import{spawn as W}from"node:child_process";import{Einblendbestand as T,torWoerter as R}from"./einblendung-kern.js";import{rahmeEin as j}from"./einblendung-rahmen.js";import{istMarkiert as V}from"./verdacht-marke.js";import{leserText as X}from"./seltenheitsbestand.js";import{mischeMitLeser as $}from"./leser.js";import{LeserSicherung as Q,dateiSpeicher as ee,frageLeser as te}from"./leser-sicherung.js";import{LESER_TIEFE_EINBLENDUNG as ne,LESER_ZEITLIMIT_MS as re}from"./rangfolge-stellschrauben.js";import{stufeEinblendungNachVersion as se}from"./gueltigkeit-version.js";import{ARME as B,BASIS_MIN_BELEGE as oe,MERKMAL_KANDIDATEN as ie,OHNE_LERNEN as le,entscheide as ae,leseArmZaehlung as ce,lernEinstellungen as ue,lernenAuffrischen as pe,merkeEntscheidung as he,neuerSatz as fe,sitzungsKennung as me,zugKennung as de}from"./lernen.js";export*from"./einblendung-kern.js";import{belohnungMelden as et,lernenAuffrischen as tt,lernEinstellungen as nt,ARME as rt}from"./lernen.js";const ge=600*1e3,z=8e3,Ee=60*1e3,H=120,U=ne,Se=1500,A=re,ke=S(k(),"cachly-ambient-netlog.jsonl");function Ze(e=process.cwd()){const t={apiUrl:process.env.CACHLY_API_URL||"https://api.cachly.dev",jwt:process.env.CACHLY_JWT||"",instanceId:process.env.CACHLY_BRAIN_INSTANCE_ID||""};if(t.jwt&&t.instanceId)return t;let n=e;for(let o=0;o<8;o++){const s=S(n,".mcp.json");if(M(s))try{const i=JSON.parse(L(s,"utf8"))?.mcpServers?.cachly?.env??{};if(t.apiUrl=t.apiUrl||i.CACHLY_API_URL||"https://api.cachly.dev",t.jwt=t.jwt||i.CACHLY_JWT||"",t.instanceId=t.instanceId||i.CACHLY_BRAIN_INSTANCE_ID||"",t.jwt&&t.instanceId)return t}catch{}const r=C(n);if(r===n)break;n=r}return t}function I(e){return G("sha1").update(e).digest("hex").slice(0,12)}function ye(e){return S(k(),`cachly-ambient-bestand-${I(e)}.json`)}function _e(e){return S(k(),`cachly-leser-sicherung-${I(e)}.json`)}function Ae(e){return S(k(),`cachly-ambient-auffrischen-${I(e)}.lock`)}async function O(e,{fetchFn:t=fetch,zeitlimitMs:n=z}={}){try{const o=await t(`${e.apiUrl}/api/v1/instances/${e.instanceId}/export`,{headers:{Authorization:`Bearer ${e.jwt}`},signal:AbortSignal.timeout(n)});if(!o.ok)return null;const s=await o.json();return Array.isArray(s?.lessons)?s.lessons.map(r=>typeof r=="string"?Ie(r):r).filter(r=>!!r&&typeof r=="object"):null}catch{return null}}function Ie(e){try{return JSON.parse(e)}catch{return null}}function P(e,t){try{K(C(e),{recursive:!0}),x(e,JSON.stringify({at:Date.now(),lessons:t}),{mode:384})}catch{}}function D(e){try{const t=JSON.parse(L(e,"utf8"));if(Array.isArray(t?.lessons))return{at:Number(t.at)||0,lessons:t.lessons}}catch{}return null}function be(e,t){const n=Ae(e.instanceId);try{if(M(n)&&Date.now()-q(n).mtimeMs<Ee)return;x(n,String(Date.now()),{mode:384})}catch{return}try{W(process.execPath,t,{detached:!0,stdio:"ignore",env:{...process.env,CACHLY_API_URL:e.apiUrl,CACHLY_JWT:e.jwt,CACHLY_BRAIN_INSTANCE_ID:e.instanceId}}).unref()}catch{}}async function we(e,{force:t=!1,nebenlauf:n,abrufMs:o=z,lernen:s=!1,fetchFn:r}={}){if(!e.jwt||!e.instanceId)return{lessons:[],quelle:"nicht-eingerichtet"};const i=ye(e.instanceId);if(t){const[l]=await Promise.all([O(e,{fetchFn:r,zeitlimitMs:o}),s?pe(e,{fetchFn:r}):void 0]);if(l)return P(i,l),{lessons:l,quelle:"server"};const m=D(i);return m?{lessons:m.lessons,quelle:"platte-alt"}:{lessons:[],quelle:"server-nicht-erreichbar"}}const p=D(i);if(p){const l=Date.now()-p.at<ge;return!l&&n&&be(e,n),{lessons:p.lessons,quelle:l?"platte":"platte-alt"}}const c=await O(e,{fetchFn:r,zeitlimitMs:o});return c?(P(i,c),{lessons:c,quelle:"server"}):{lessons:[],quelle:"server-nicht-erreichbar"}}function b(e){return Math.ceil(String(e).length/4)}function w(e){const t=e.severity?`[${e.severity}] `:"",n=String(e.what_worked??"").replace(/\s+/g," ").trim(),o=n.length>H?`${n.slice(0,H)}\u2026`:n,s=typeof e.versionshinweis=="string"?` [${e.versionshinweis}]`:"";return`- ${t}${e.topic}${s}: ${o}`}const y={lessons:[],tokens:0,topScore:0,belege:0};function N(e,t,n){if(e.length===0)return{...y};const o=[];let s=0;e=se(e);for(const{lektion:r}of e.slice(0,t)){const i=b(w(r));if(s+i>n)break;o.push(r),s+=i}return{lessons:o,tokens:s,topScore:Math.round(e[0].punkte*100)/100,belege:e[0].belege}}function Je(e,t,{minBelege:n=2,topK:o=3,tokenBudget:s=600}={}){if(!Array.isArray(t)||t.length===0)return{...y};if(R(e).length===0)return{...y};const r=new T(t).sortiere(e).filter(i=>i.belege>=n);return r.length===0?{...y}:N(r,o,s)}function Ne(e){return X(e,Se)}async function Y(e,t,n,{zeitlimitMs:o=A,fetchFn:s}={}){if(!e?.jwt||!e?.instanceId||n.length===0)return{art:"ohne"};if(["0","off","aus","false"].includes(String(process.env.CACHLY_LESER||"").toLowerCase()))return{art:"ohne"};const r=new Q(ee(_e(e.instanceId)));return te({url:`${e.apiUrl}/api/v1/rerank`,jwt:e.jwt,frage:t,texte:n,instanceId:e.instanceId,zeitlimitMs:o,fetchFn:s},r)}async function Ke(e,t,n,o={}){const s=await Y(e,t,n,o);return s.art==="punkte"?{scores:s.scores,provider:s.provider,ms:s.ms}:null}async function Z(e,t,n,{minBelege:o,tiefe:s,zeitlimitMs:r,fetchFn:i}){const p={sortiert:[],leser:"aus",leserMs:0};if(!Array.isArray(t)||t.length===0||R(e).length===0)return p;let c=new T(t).sortiere(e).filter(h=>h.belege>=o);if(c.length===0)return p;let l="aus",m=0;if(c.length>1&&s>0){const h=c.slice(0,s),g=c.slice(s),f=await Y(n,e,h.map(E=>Ne(E.lektion)),{zeitlimitMs:r,fetchFn:i});f.art==="punkte"?(c=[...$(h.map(u=>u.punkte),f.scores,1).map(u=>({...h[u],leser:f.scores[u]})),...g],l=f.provider,m=f.ms):f.art==="uebersprungen"&&(l="uebersprungen")}return{sortiert:c,leser:l,leserMs:m}}async function qe(e,t,n,{minBelege:o=2,topK:s=3,tokenBudget:r=600,tiefe:i=U,zeitlimitMs:p=A,fetchFn:c}={}){const l=await Z(e,t,n,{minBelege:o,tiefe:i,zeitlimitMs:p,fetchFn:c});return{...N(l.sortiert,s,r),leser:l.leser,leserMs:l.leserMs}}function ve(e){if(!e.lessons.length)return"";const t=e.lessons.map(w).join(`
2
2
  `);return`\u{1F9E0} Cachly Brain \u2014 relevant lessons for this task (auto-recall, ${e.lessons.length}):
3
- ${N(t)}
4
- (ambient-recall \xB7 ~${e.tokens} tokens \xB7 match score ${e.topScore})`}const fe=5;function Le(e){if(!e.length)return"";const t=e.filter(r=>{const s=String(r.topic??"");return!(/^auto:/.test(s)||/^[a-z]+:?$/.test(s))}),o=[...t.length?t:e].sort((r,s)=>(Number(s.recall_count)||0)-(Number(r.recall_count)||0)).slice(0,fe).map(E).join(`
5
- `);return`\u{1F9E0} Cachly Brain \u2014 ambient recall active (${e.length} lessons). Top by proven reuse:
6
- ${N(o)}
7
- (Relevant lessons for each task are auto-injected per prompt. ~${g(o)} tokens.)`}function Ne(e,t){return t?JSON.stringify({hookSpecificOutput:{hookEventName:e,additionalContext:t}}):""}async function Ce(e,t,{nebenlauf:n,abrufMs:o,leser:r=!0,session:s=null,protokoll:i=!0,fetchFn:u}={}){const{lessons:c,quelle:l}=await ce(t,{nebenlauf:n,abrufMs:o,fetchFn:u}),a=await ue(e,c,t,{tiefe:r?$:0,fetchFn:u});if(i)try{J(ne,JSON.stringify({at:Date.now(),session:s,prompt_tokens:g(e),injected_tokens:a.tokens,matches:a.lessons.length,top_score:a.topScore,belege:a.belege,leser:a.leser,leser_ms:a.leserMs,quelle:l,bestand:c.length})+`
8
- `)}catch{}return{kontext:pe(a),auswahl:a,quelle:l,bestand:c.length}}export{T as ABRUF_TIMEOUT_MS,j as ANZEIGE_ZEICHEN,Q as BESTAND_TTL_MS,R as LESER_HOOK_ZEITLIMIT_MS,te as LESER_MAX_ZEICHEN,$ as LESER_TIEFE,ne as NETZ_PROTOKOLL,fe as SITZUNG_TOP_N,re as bestandPfad,g as estimateTokens,ce as holeBestand,Ne as hookAusgabe,B as leserAnfrageApi,xe as leserPunkteApi,le as leserText,C as mischeMitLeser,Ce as promptEinblendung,pe as promptKontext,E as renderLesson,be as resolveConfig,ke as selectRelevant,ue as selectRelevantMitLeser,se as sicherungsPfad,Le as sitzungsKontext,ae as starteNebenlauf};
3
+ ${j(t)}
4
+ (ambient-recall \xB7 ~${e.tokens} tokens \xB7 match score ${e.topScore})`}const Le=5;function Fe(e){const t=e.filter(r=>!V(r));if(!t.length)return"";const n=t.filter(r=>{const i=String(r.topic??"");return!(/^auto:/.test(i)||/^[a-z]+:?$/.test(i))}),s=[...n.length?n:t].sort((r,i)=>(Number(i.recall_count)||0)-(Number(r.recall_count)||0)).slice(0,Le).map(w).join(`
5
+ `);return`\u{1F9E0} Cachly Brain \u2014 ambient recall active (${t.length} lessons). Top by proven reuse:
6
+ ${j(s)}
7
+ (Relevant lessons for each task are auto-injected per prompt. ~${b(s)} tokens.)`}function Ge(e,t){return t?JSON.stringify({hookSpecificOutput:{hookEventName:e,additionalContext:t}}):""}function Me(e,t){return e.map((n,o)=>({x:n,rang:o,gezeigt:t.includes(n.lektion)})).filter(({rang:n,gezeigt:o})=>n<ie||o).map(({x:n,rang:o,gezeigt:s})=>({thema:String(n.lektion.topic??""),rang:o,punkte:Math.round(n.punkte*1e3)/1e3,belege:n.belege,leser:typeof n.leser=="number"&&Number.isFinite(n.leser)?Math.round(n.leser*1e3)/1e3:null,gezeigt:s}))}async function We(e,t,{nebenlauf:n,abrufMs:o,leser:s=!0,session:r=null,protokoll:i=!0,ereignis:p="UserPromptSubmit",editor:c="",lernen:l=!0,fetchFn:m}={}){const{lessons:h,quelle:g}=await we(t,{nebenlauf:n,abrufMs:o,fetchFn:m}),f=ue(),E=l&&f.aktiv&&p==="UserPromptSubmit"&&!!t.instanceId,u=E?ae({instanceId:t.instanceId,sitzung:r,prompt:e,zaehlung:ce(t.instanceId),einstellungen:f}):le,v=B[u.arm]??B[0],d=await Z(e,h,t,{minBelege:oe,tiefe:s?U:0,zeitlimitMs:A,fetchFn:m}),a={...N(d.sortiert.filter(J=>J.belege>=v.minBelege),v.topK,600),leser:d.leser,leserMs:d.leserMs},_=u.kontrolle?"":ve(a);if(E&&d.sortiert.length>0&&he(t.instanceId,r,fe({sitzung:me(r),zug:de(e),ereignis:p,editor:c,arm:u.arm,kontrolle:u.kontrolle,erkundet:u.erkundet,ausgewaehlt:a.lessons.length,kandidatenZahl:d.sortiert.length,belege:a.belege,topScore:a.topScore,leser:a.leser,leserMs:a.leserMs,quelle:g,bestand:h.length,kandidaten:Me(d.sortiert,a.lessons)})),i)try{F(ke,JSON.stringify({at:Date.now(),session:r,prompt_tokens:b(e),injected_tokens:_?a.tokens:0,matches:_?a.lessons.length:0,arm:u.arm,kontrolle:u.kontrolle,ausgewaehlt:a.lessons.length,top_score:a.topScore,belege:a.belege,leser:a.leser,leser_ms:a.leserMs,quelle:g,bestand:h.length})+`
8
+ `)}catch{}return{kontext:_,auswahl:a,quelle:g,bestand:h.length,entscheidung:u}}export{z as ABRUF_TIMEOUT_MS,H as ANZEIGE_ZEICHEN,rt as ARME,ge as BESTAND_TTL_MS,A as LESER_HOOK_ZEITLIMIT_MS,Se as LESER_MAX_ZEICHEN,U as LESER_TIEFE,ke as NETZ_PROTOKOLL,Le as SITZUNG_TOP_N,et as belohnungMelden,ye as bestandPfad,b as estimateTokens,we as holeBestand,Ge as hookAusgabe,nt as lernEinstellungen,tt as lernenAuffrischen,Y as leserAnfrageApi,Ke as leserPunkteApi,Ne as leserText,$ as mischeMitLeser,We as promptEinblendung,ve as promptKontext,w as renderLesson,Ze as resolveConfig,Je as selectRelevant,qe as selectRelevantMitLeser,_e as sicherungsPfad,Fe as sitzungsKontext,be as starteNebenlauf};
@@ -1,12 +1,12 @@
1
- import{ckgSlug as j}from"../ckg.js";import{safeJsonParse as x,darfHeraus as L}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 H}from"../leeres-brain.js";function I(C){return L(C)&&!C.group}const V=new Set(["memory_consolidate","brain_diff","causal_trace","knowledge_decay","autopilot"]);async function q(C,A,M,N){switch(C){case"memory_consolidate":{const{instance_id:l,dry_run:u=!1,stale_days:w=90}=A,p=await M(l),$=Date.now(),h=w*86400*1e3;let f=0;const m=[];do{const[n,a]=await p.scan(f,"MATCH","cachly:lesson:best:*","COUNT",200);f=parseInt(n),m.push(...a)}while(f!==0);if(m.length===0)return"\u{1F9E0} **Brain is empty** \u2014 no lessons to consolidate yet. Use `learn_from_attempts` after your next bug fix.";const r=new Map;for(const n of m){const a=await p.get(n);if(!a)continue;const e=x(a,null);e&&r.set(n,e)}const _=new Map;for(const[n,a]of r){const e=a.topic.split(":")[0],o=_.get(e)??[];o.push(n),_.set(e,o)}const k=[...r.values()],v=F(k),b=v.filter(n=>n.beziehung==="widerspruch"),g=v.filter(n=>n.beziehung==="ersetzung"),y=[],s=new Map;for(const[n,a]of r){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=>r.get(o)?.outcome)).size>1&&y.push({topic:n,keys:a});const t=[];for(const[n,a]of r){const e=$-new Date(a.ts).getTime(),o=a.recall_count??0;e>h&&o===0&&t.push(n)}const i=0;if(!u)for(const n of t)await p.expire(n,86400*30);return[`\u{1F52C} **Memory Consolidation Report** ${u?"(dry run \u2014 no changes made)":"\u2705 Applied"}`,"",`\u{1F4CA} **Before:** ${m.length} lessons`,"",`\u{1F501} **Contradictions \u2014 exact topic match (old rule):** ${y.length}`,`\u{1F50E} **Same subject, admitted for judgement:** ${v.length} \u2192 contradiction ${b.length} \xB7 supersession ${g.length}`,...b.slice(0,5).map(n=>` \u2192 \`${n.a.topic}\` vs \`${n.b.topic}\` (${n.naehe.toFixed(2)}): ${n.grund}`),b.length>5?` \u2026 and ${b.length-5} more`:"",...g.slice(0,3).map(n=>` \u21BB \`${n.a.topic}\` \u2192 \`${n.b.topic}\`: ${n.grund}`),...y.slice(0,5).map(n=>` \u2192 \`${n.topic}\`: ${n.keys.length} conflicting entries (kept: success)`),y.length>5?` \u2026 and ${y.length-5} more`:"","",`\u267B\uFE0F **Duplicate clusters (counted, never deleted):** ${Array.from(_.values()).filter(n=>n.length>1).length}`,"",`\u{1F570}\uFE0F **Stale entries (${w}d, 0 recalls):** ${t.length}`+(t.length>0&&!u?" \u2192 set to expire in 30 days":""),"",`\u{1F4CA} **After:** ${m.length-i} lessons`,"",u?"\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:u="7d",format:w="summary"}=A,p=await M(l);let $;const h=u.match(/^(\d+)([dhm])$/);if(h){const e=parseInt(h[1]),o=h[2],c=o==="d"?864e5:o==="h"?36e5:6e4;$=Date.now()-e*c}else $=new Date(u).getTime()||Date.now()-7*864e5;let f=0;const m=[];do{const[e,o]=await p.scan(f,"MATCH","cachly:lesson:best:*","COUNT",200);f=parseInt(e),m.push(...o)}while(f!==0);const r=[],_=[],k=[],v=m.length;for(const e of m){const o=await p.get(e);if(o){const c=x(o,null);if(!c)continue;if(new Date(c.ts).getTime()>=$){const T=`cachly:lesson:history:${c.topic}`;await p.llen(T)<=1?r.push(c):_.push(c)}(c.recall_count??0)>0&&k.push(c)}}const g=[`\u{1F4CA} **Brain Diff** \u2014 ${h?`last ${u}`:new Date($).toLocaleDateString("de-DE")}`,"",`Total lessons in brain: **${v}**`,"",`\u2705 **New** (${r.length}):`,...r.slice(0,w==="detailed"?20:5).map(e=>` + \`${e.topic}\` \u2014 ${e.outcome} ${e.severity==="critical"?"\u{1F534}":e.severity==="major"?"\u{1F7E0}":"\u{1F7E2}"}`),r.length>5&&w==="summary"?` \u2026 and ${r.length-5} more`:"","",`\u{1F504} **Updated** (${_.length}):`,..._.slice(0,w==="detailed"?20:5).map(e=>` ~ \`${e.topic}\` \u2014 now: ${e.outcome}`),_.length>5&&w==="summary"?` \u2026 and ${_.length-5} more`:"","",`\u{1F50D} **Active** (recalled at least once): ${k.length}`,""].filter(e=>e!==""),y=[],s=p.scanStream({match:"cachly:ckg:node:resolution-*",count:100});await new Promise((e,o)=>{s.on("data",c=>y.push(...c)),s.on("end",e),s.on("error",o)});const t=[];for(const e of y){const o=await p.get(e);if(o){const c=x(o,null);c?.ts&&new Date(c.ts).getTime()>=$&&t.push({topic:c.topic??e,resolution:c.resolution??"unknown",ts:c.ts})}}if(t.length>0){g.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";g.push(` ${o} \`${e.topic}\` \u2192 ${e.resolution}`)}g.push("")}const i=new Set(_.concat(k).map(e=>e.topic.split(":")[0])),d=[...new Set(r.map(e=>e.topic.split(":")[0]))].filter(e=>!i.has(e));d.length>0&&g.push(`\u{1F331} **New domains bootstrapped:** ${d.map(e=>`\`${e}\``).join(", ")}`,"");const a=(await p.lrange("cachly:fedbrain:federations",-20,-1)).map(e=>x(e,null)).filter(e=>e!==null&&new Date(e.transferred_at).getTime()>=$);if(a.length>0){g.push(`\u{1F9E0} **FedBrain transfers received (${a.length}):**`);for(const e of a.slice(0,3))g.push(` \u{1F4E5} domain \`${e.domain}\` from \`${e.source.slice(0,16)}\u2026\` \u2014 ${e.nodes} nodes, ${e.edges} edges`);g.push("")}return g.push("\u{1F4A1} Run `memory_consolidate` to merge duplicates \xB7 `knowledge_decay` to see confidence scores."),g.join(`
3
- `)}case"causal_trace":{const{instance_id:l,problem:u,max_depth:w=5,tags:p=[]}=A,$=await H(l,N,`\u{1F50D} **Causal Trace: "${u}"**
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}"**
4
4
 
5
- No matching lessons found in brain.`);if($)return $;const h=await M(l),f=u.toLowerCase().replace(/[^a-z0-9\s\-_:]/g," ").split(/\s+/).filter(t=>t.length>2),m={critical:"\u{1F534}",major:"\u{1F7E0}",minor:"\u{1F7E1}"},r=[];try{for(const t of f.slice(0,4)){const i=await h.smembers(`cachly:ckg:idx:from:${j(t)}`),d=await h.smembers(`cachly:ckg:idx:to:${j(t)}`),n=[],a=h.scanStream({match:`cachly:ckg:node:*${t}*`,count:50});await new Promise((e,o)=>{a.on("data",c=>n.push(...c)),a.on("end",e),a.on("error",o)});for(const e of n.slice(0,10)){const o=await h.get(e);if(!o)continue;const c=x(o,null);if(!c)continue;const D=await h.smembers(`cachly:ckg:idx:from:${c.id}`);for(const T of D.slice(0,20)){const R=await h.get(T);if(!R)continue;const S=x(R,null);if(!S||S.edgeType!=="fixes"&&S.edgeType!=="requires")continue;const E=await h.get(`cachly:lesson:best:${S.from.replace(/-/g,":").replace(/^fix:/,"fix:")}`),B=E?x(E,null)??void 0:void 0;r.push({conceptId:c.id,edge:S,lesson:B&&I(B)?B:void 0})}}for(const e of[...i,...d].slice(0,20)){const o=await h.get(e);if(!o)continue;const c=x(o,null);if(!c)continue;const D=await h.get(`cachly:lesson:best:${c.from}`),T=D?x(D,null)??void 0:void 0;r.push({conceptId:c.from,edge:c,lesson:T&&I(T)?T:void 0})}}}catch{}const _=new Set,k=r.filter(t=>{const i=`${t.edge.from}:${t.edge.edgeType}:${t.edge.to}`;return _.has(i)?!1:(_.add(i),!0)}).sort((t,i)=>i.edge.confidence-t.edge.confidence).slice(0,w);let v=0;const b=[];do{const[t,i]=await h.scan(v,"MATCH","cachly:lesson:*","COUNT",200);v=parseInt(t),b.push(...i)}while(v!==0);const g=[];for(const t of b){const i=await h.get(t);if(i){const d=x(i,null);if(!d||!I(d)||p.length>0&&!(d.tags??[]).some(e=>p.includes(e)))continue;const n=[d.topic,d.what_failed??"",d.what_worked??"",d.context??""].join(" ").toLowerCase(),a=f.reduce((e,o)=>e+(n.includes(o)?1:0),0);a>0&&g.push({score:a,lesson:d,key:t})}}g.sort((t,i)=>i.score-t.score);const y=g.slice(0,w);if(y.length===0&&k.length===0)return[`\u{1F50D} **Causal Trace: "${u}"**`,"","No matching lessons found in brain.","","\u{1F4A1} After you solve this, call:","```","learn_from_attempts(",` instance_id = "${l}",`,` topic = "fix:${f[0]??"issue"}",`,' outcome = "success",',' what_worked = "...",',` what_failed = "${u}",`,")","```"].join(`
6
- `);const s=[`\u{1F50D} **Causal Trace: "${u}"**`,""];if(k.length>0){s.push("### \u{1F578}\uFE0F CKG Graph (confidence-ranked)");for(const t of k){const i=Math.round(t.edge.confidence*100),d="\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(` ${d} ${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(y.length>0){s.push(k.length>0?`### \u{1F4DA} Text Search (${y.length} related lessons)`:`Found **${y.length}** related lessons. Reconstructed causal chain:`,"");const t=y.filter(n=>n.lesson.outcome!=="success"),i=y.filter(n=>n.lesson.outcome==="success");t.length>0&&(s.push("**Root causes & failure chain:**"),t.forEach((n,a)=>{const e=n.lesson,o=m[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 d=i[0]?.lesson;if(d?.what_worked){s.push("**\u26A1 Most likely fix:**"),s.push("```"),s.push(d.what_worked.slice(0,500)),s.push("```"),s.push("");const n=O(d)?K(d,"trace"):0;n>0&&h.incrbyfloat(`cachly:stats:time_saved_mins:${l}`,n).catch(()=>{})}}return s.push(`\u{1F4A1} After applying: \`learn_from_attempts(topic="fix:${f[0]??"issue"}", outcome="success", ...)\``),k.length>0&&s.push(`\u{1F578}\uFE0F Explore graph: \`ckg_inspect(concept="${f[0]??"fix"}")\``),s.join(`
7
- `)}case"knowledge_decay":{let k=function(s){const t=Math.round(s/10);return"\u2588".repeat(t)+"\u2591".repeat(10-t)+` ${s}%`};const{instance_id:l,min_age_days:u=0,show_top:w=20}=A,p=await M(l),$=Date.now(),h=u*864e5;let f=0;const m=[];do{const[s,t]=await p.scan(f,"MATCH","cachly:lesson:best:*","COUNT",200);f=parseInt(s),m.push(...t)}while(f!==0);const r=[];for(const s of m){const t=await p.get(s);if(t){const i=x(t,null);if(!i)continue;const d=$-new Date(i.ts).getTime();if(d<h)continue;const n=Math.floor(d/864e5),a=i.recall_count??0,e=Math.max(0,n-7),o=Math.max(5,100-e),c=Math.min(50,a*5),D=i.outcome==="failure"?-20:0,T=Math.min(100,Math.max(0,o+c+D));r.push({topic:i.topic,confidence:T,age_days:n,recalls:a,outcome:i.outcome})}}r.sort((s,t)=>s.confidence-t.confidence);const _=r.slice(0,w),v=r.length>0?Math.round(r.reduce((s,t)=>s+t.confidence,0)/r.length):0,b=r.filter(s=>s.confidence<30).length,g=r.filter(s=>s.confidence>=70).length;return[`\u{1F9EA} **Knowledge Decay Report** \u2014 ${r.length} lessons`,"",`Average confidence: **${k(v)}**`,`\u{1F534} Critical (<30%): ${b} \u{1F7E2} Healthy (\u226570%): ${g}`,"","Lowest confidence lessons (fix these first):","",..._.map((s,t)=>`${(t+1).toString().padStart(2)}. \`${s.topic}\`
8
- ${k(s.confidence)} \xB7 ${s.age_days}d old \xB7 ${s.recalls} recalls \xB7 ${s.outcome}`),"",r.length>w?`\u2026 and ${r.length-w} 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(s=>s!=="").join(`
9
- `)}case"autopilot":{const{instance_id:l,editor:u="claude",project_name:w="this project",style:p="full"}=A,$=`## Cachly AI Brain \u2014 Autopilot
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
10
10
 
11
11
  **Instance:** \`${l}\`
12
12
 
@@ -22,7 +22,7 @@ No matching lessons found in brain.`);if($)return $;const h=await M(l),f=u.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
- `,h=`## Cachly AI Brain \u2014 Autopilot for ${w}
25
+ `,w=`## 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
- `,f=p==="minimal"?$:h,m=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:** \`${m}\` \u2014 create it, or APPEND to your existing one`,"","```markdown",f,"```","",`**How to apply** (\`>>\` appends \u2014 an existing ${m} keeps every line you wrote):`,"```bash",`cat >> ${m} << '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{V as ADVANCED_TOOL_NAMES,q as handleAdvancedTool};
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};