@cachly-dev/mcp-server 0.10.224 → 0.10.226
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 +11 -6
- package/dist/src/aussetzer.js +1 -1
- package/dist/src/embeddings.js +4 -4
- package/dist/src/first-recall-proof.js +4 -4
- package/dist/src/git-startpunkt.js +1 -0
- package/dist/src/handlers/advanced.js +2 -2
- package/dist/src/handlers/brain.js +61 -66
- package/dist/src/handlers/fedbrain.js +37 -37
- package/dist/src/handlers/share.js +16 -16
- package/dist/src/handlers/syndicate.js +2 -2
- package/dist/src/handlers/team.js +25 -25
- package/dist/src/index.js +131 -135
- package/dist/src/pflichtfelder.js +1 -0
- package/dist/src/projektdateien.js +10 -4
- package/dist/src/schreibtor.js +1 -1
- package/dist/src/tuersteher.js +1 -1
- package/dist/src/uninstall.js +4 -4
- package/dist/src/wirkungsspur.js +1 -1
- package/glama.json +1 -1
- package/hooks/cachly-ambient-einblendung.mjs +17 -17
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -67,7 +67,8 @@ npx @cachly-dev/mcp-server@latest autopilot
|
|
|
67
67
|
`autopilot` finds the editors you use and writes the MCP config for each. It also writes
|
|
68
68
|
the rule file each editor reads in every chat (`CLAUDE.md`, `AGENTS.md`,
|
|
69
69
|
`.cursor/rules/cachly.mdc`, `.github/copilot-instructions.md`, `.windsurfrules`,
|
|
70
|
-
`.clinerules`
|
|
70
|
+
`.clinerules`; `GEMINI.md`, `.junie/guidelines.md` and `.continue/rules/cachly.md` where
|
|
71
|
+
you use Gemini CLI, Junie or Continue), which tells your AI to check its memory before a task. It adds a git
|
|
71
72
|
hook that learns from your commits and fills your Brain from your git history. You sign
|
|
72
73
|
in once in the browser (a device code, no password, no credit card), so the Brain
|
|
73
74
|
belongs to your own account from the start. Restart your editor afterwards.
|
|
@@ -75,8 +76,8 @@ belongs to your own account from the start. Restart your editor afterwards.
|
|
|
75
76
|
You can also add the server by hand (see [Manual Setup](#manual-setup)). Without a key,
|
|
76
77
|
the first tool call creates the same test Brain as in Claude Code. Without a rule file,
|
|
77
78
|
Claude Code still starts each task with `smart_recall`, because the server's instructions
|
|
78
|
-
ask for it.
|
|
79
|
-
there, the rule file from `autopilot` is what makes your AI use its memory.
|
|
79
|
+
ask for it. Gemini CLI also passes them on. Some editors do not (Cline, Continue and Zed,
|
|
80
|
+
for example); there, the rule file from `autopilot` is what makes your AI use its memory.
|
|
80
81
|
|
|
81
82
|
> **Already inside Claude, Cursor or Copilot?** Paste this to your AI:
|
|
82
83
|
> ```
|
|
@@ -342,7 +343,7 @@ Manual snippets are in [Manual Setup](#manual-setup).
|
|
|
342
343
|
|
|
343
344
|
| Editor / client | Auto-setup | Config file written | Global config | Notes |
|
|
344
345
|
|---|---|---|---|---|
|
|
345
|
-
| **Claude Code** | yes |
|
|
346
|
+
| **Claude Code** | yes | `.mcp.json` | with the plugin | Without a key: test Brain at session start (plugin) or on the first tool call; browser sign-in only as fallback |
|
|
346
347
|
| **Cursor** | yes, detected via `.cursor/` | `.cursor/mcp.json`, hooks in `.cursor/hooks.json` | no | Project-level; restart Cursor after setup. Lessons arrive with the first tool call of a turn |
|
|
347
348
|
| **Windsurf** | yes, detected via `.windsurf/` | `.windsurf/mcp.json` | no | Project-level; restart Windsurf after setup |
|
|
348
349
|
| **VS Code + Copilot** | yes, detected via `.vscode/` | `.vscode/mcp.json`, hooks in `.github/hooks/cachly-ambient.json` | no | Needs the VS Code MCP support or Copilot chat. Briefing at session start, lessons before each prompt |
|
|
@@ -360,14 +361,14 @@ Manual snippets are in [Manual Setup](#manual-setup).
|
|
|
360
361
|
|---|---|
|
|
361
362
|
| `autosetup` or `autopilot` from a terminal (TTY) | OAuth device flow: one click in the browser, the API key is saved automatically |
|
|
362
363
|
| `autosetup` from a VS Code task or CI (no TTY) | Detects the non-interactive run, opens the browser with a step-by-step guide, prints the `CACHLY_JWT=... autosetup` command |
|
|
363
|
-
| First tool call without any key | Test Brain: an anonymous Brain on EU servers. The key is saved to `~/.cachly/credentials.json
|
|
364
|
+
| First tool call without any key | Test Brain: an anonymous Brain on EU servers. The key is saved to `~/.cachly/credentials.json`, and the call goes through. If that fails (offline, rate limit), the inline device flow starts with a URL and a code |
|
|
364
365
|
| First tool call with `CACHLY_BRAIN_INSTANCE_ID` set but no key | Inline device flow. You already have a Brain, so no second account is created |
|
|
365
366
|
| `CACHLY_JWT=cky_live_xxx npx ... autosetup` | Skips the sign-in step and uses the key you pass |
|
|
366
367
|
|
|
367
368
|
## Manual Setup
|
|
368
369
|
|
|
369
370
|
<details>
|
|
370
|
-
<summary><b>Claude Code</b> (<code
|
|
371
|
+
<summary><b>Claude Code</b> (<code>.mcp.json</code> in the project)</summary>
|
|
371
372
|
|
|
372
373
|
```json
|
|
373
374
|
{
|
|
@@ -380,6 +381,10 @@ Manual snippets are in [Manual Setup](#manual-setup).
|
|
|
380
381
|
}
|
|
381
382
|
```
|
|
382
383
|
|
|
384
|
+
For all your projects at once, use the plugin above, or
|
|
385
|
+
`claude mcp add -s user cachly -- npx -y @cachly-dev/mcp-server@latest`
|
|
386
|
+
(Claude Code stores that in `~/.claude.json`).
|
|
387
|
+
|
|
383
388
|
Without a key, the first tool call creates a test Brain on EU servers. No sign-up.
|
|
384
389
|
Run `npx @cachly-dev/mcp-server@latest autopilot` to use your own account instead.
|
|
385
390
|
</details>
|
package/dist/src/aussetzer.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const s=new Set;let u=!1;function l(){u=!0}function f(e){if(e instanceof Error)return(e.message||e.name||"Error").slice(0,200);if(typeof e=="string")return e.slice(0,200)||"leerer Text geworfen";if(e===void 0)return"undefined geworfen (kein Grund mitgegeben)";if(e===null)return"null geworfen (kein Grund mitgegeben)";try{const n=JSON.stringify(e);return n&&n!=="{}"?n.slice(0,200):`${typeof e} ohne Inhalt geworfen`}catch{return`${typeof e} geworfen, nicht darstellbar`}}function c(e,n){return s.has(e)?!1:(s.add(e),u||console.error(`[aussetzer] ${e}: ${n}`),!0)}function h(e){return s.has(e)}function g(){return[...s]}function E(){s.clear(),u=!1}const m="bedeutung-ohne-vektoren",p="bedeutung-ohne-dienst",x="bedeutung-ohne-fragevektor",d="bedeutung-abbruch",z="einbettung-beim-schreiben",k="versuch-laeuft-leer",a="cachly:aussetzer:",i=720*60*60;async function y(e,n,o){const r=c(n,o);if(!e)return r;try{const t=`${a}${n}`;await e.hincrby(t,"anzahl",1),await e.hset(t,{zuletzt:new Date().toISOString(),text:o.slice(0,500)}),await e.expire(t,i)}catch(t){c(`${n}-vermerk`,`der Aussetzer liess sich nicht vermerken (${t instanceof Error?t.message:String(t)}) \u2014 er steht nur in diesem Protokoll und ist nach einem Neustart weg`)}return r}async function S(e){if(!e)return null;try{const n=await e.keys(`${a}*`),o=[];for(const r of n){const t=await e.hgetall(r);!t||!t.anzahl||o.push({grund:r.slice(a.length),anzahl:Number(t.anzahl)||0,zuletzt:t.zuletzt??"",text:t.text??""})}return o.sort((r,t)=>t.anzahl-r.anzahl||r.grund.localeCompare(t.grund)),o}catch{return null}}export{i as AUSSETZER_TTL_SEKUNDEN,a as AUSSETZER_VORSATZ,p as OHNE_DIENST,x as OHNE_FRAGEVEKTOR,z as OHNE_SCHREIBVEKTOR,m as OHNE_VEKTOREN,d as SINNPFAD_ABBRUCH,k as VERSUCH_LEER,l as aussetzerLeise,f as fehlerText,g as gemeldeteGruende,S as leseVermerke,c as meldeEinmal,y as meldeUndVermerke,h as schonGemeldet,E as setzeAussetzerZurueck};
|
package/dist/src/embeddings.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import{zeitpunkt as
|
|
1
|
+
import{zeitpunkt as A}from"./zeitmessung.js";const i={apiUrl:process.env.CACHLY_API_URL??"https://api.cachly.dev",jwt:process.env.CACHLY_JWT??"",model:process.env.CACHLY_EMBED_MODEL??""};function R(r){i.jwt=r,r&&!I&&d==="none"&&(d="cachly")}const h=Number(process.env.CACHLY_EMBED_TIMEOUT_MS??8e3),p=Number(process.env.CACHLY_EMBED_TIMEOUT_MAX_MS??45e3),g=12;function f(r,n){return n==="kurz"?h:Math.min(p,h+r.length*g)}function b(){return process.env.CACHLY_JWT?"cachly":process.env.OLLAMA_BASE_URL?"ollama":"none"}const I=!!process.env.CACHLY_EMBED_PROVIDER;let d=(process.env.CACHLY_EMBED_PROVIDER??b()).toLowerCase();async function y(r,n,s){const c=f(r,n);switch(d){case"cachly":{if(!i.jwt)throw new Error(`CACHLY_JWT not set.
|
|
2
2
|
|
|
3
3
|
The "cachly" provider uses server-side embeddings via the Cachly API.
|
|
4
4
|
Set CACHLY_JWT, or use another provider via CACHLY_EMBED_PROVIDER:
|
|
5
5
|
openai \u2192 OPENAI_API_KEY
|
|
6
6
|
gemini \u2192 GEMINI_API_KEY
|
|
7
|
-
ollama \u2192 OLLAMA_BASE_URL (local, no key needed)`);const e=`${
|
|
7
|
+
ollama \u2192 OLLAMA_BASE_URL (local, no key needed)`);const e=`${i.apiUrl}/api/v1/embed`,o={text:r};(s??i.model)&&(o.model=s??i.model);const t=process.env.CACHLY_ADMIN_KEY??"",a=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i.jwt}`,...t?{"X-Admin-Key":t}:{}},body:JSON.stringify(o),signal:AbortSignal.timeout(c)});if(!a.ok){const _=await a.text();let E=null;const m=Number(a.headers.get("retry-after"));if(Number.isFinite(m)&&m>=0)E=m;else try{const u=JSON.parse(_);typeof u.retry_after=="number"&&u.retry_after>=0&&(E=u.retry_after)}catch{}throw Object.assign(new Error(`Cachly embed API error ${a.status}: ${_.slice(0,200)}`),{status:a.status,retryAfterSek:E})}return(await a.json()).embedding}case"mistral":{const e=process.env.MISTRAL_API_KEY;if(!e)throw new Error("MISTRAL_API_KEY not set");const o=i.model!=="text-embedding-3-small"?i.model:"mistral-embed",t=await fetch("https://api.mistral.ai/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:o,input:[r]}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Mistral embedding error: ${t.statusText}`);const a=await t.json();if(!a.data?.[0]?.embedding)throw new Error("Mistral returned empty embedding response");return a.data[0].embedding}case"cohere":{const e=process.env.COHERE_API_KEY;if(!e)throw new Error("COHERE_API_KEY not set");const o=i.model!=="text-embedding-3-small"?i.model:"embed-english-v3.0",t=await fetch("https://api.cohere.com/v2/embed",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:o,texts:[r],input_type:"search_query",embedding_types:["float"]}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Cohere embedding error: ${t.statusText}`);return(await t.json()).embeddings.float[0]}case"ollama":{const e=process.env.OLLAMA_BASE_URL??"http://localhost:11434",o=s??(i.model!=="text-embedding-3-small"?i.model:"nomic-embed-text"),t=await fetch(`${e}/api/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:o,prompt:r}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Ollama embedding error: ${t.statusText}`);return(await t.json()).embedding}case"gemini":{const e=process.env.GEMINI_API_KEY;if(!e)throw new Error("GEMINI_API_KEY not set");const o=i.model!=="text-embedding-3-small"?i.model:"text-embedding-004",t=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${o}:embedContent?key=${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:`models/${o}`,content:{parts:[{text:r}]}}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Gemini embedding error: ${t.statusText}`);return(await t.json()).embedding.values}case"openai":{const e=process.env.OPENAI_API_KEY;if(!e)throw new Error(`OPENAI_API_KEY not set.
|
|
8
8
|
|
|
9
9
|
Set OPENAI_API_KEY in your .env, or switch provider:
|
|
10
10
|
CACHLY_EMBED_PROVIDER=gemini (+ GEMINI_API_KEY)
|
|
11
11
|
CACHLY_EMBED_PROVIDER=ollama (local, free)
|
|
12
|
-
CACHLY_EMBED_PROVIDER=cachly (server-side, no key needed)`);const o=
|
|
13
|
-
Supported: cachly (default), openai, mistral, cohere, ollama, gemini`)}}const
|
|
12
|
+
CACHLY_EMBED_PROVIDER=cachly (server-side, no key needed)`);const o=i.model||"text-embedding-3-small",t=await fetch("https://api.openai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:o,input:r}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`OpenAI embedding error: ${t.statusText}`);const a=await t.json();if(!a.data?.[0]?.embedding)throw new Error("OpenAI returned empty embedding response");return a.data[0].embedding}default:throw new Error(`Unknown CACHLY_EMBED_PROVIDER="${d}".
|
|
13
|
+
Supported: cachly (default), openai, mistral, cohere, ollama, gemini`)}}const w=3,C=4;function M(r){const n=r;if(typeof n?.status=="number")return n.status===429||n.status>=500;if(n?.name==="TimeoutError"||n?.name==="AbortError")return!1;if(/fetch failed/i.test(String(n?.message??"")))return!0;const s=n?.cause?.code??"";return["ECONNRESET","ECONNREFUSED","ETIMEDOUT","EAI_AGAIN","EPIPE","UND_ERR_SOCKET"].includes(s)}function O(r,n,s){if(n>=(s==="lang"?C:w)||!M(r))return null;const e=r?.retryAfterSek;if(typeof e=="number"&&Number.isFinite(e)&&e>=0){const o=e*1e3;return s==="kurz"?o<=2e3?o:null:Math.min(o,61e3)}return s==="lang"?Math.min(1e3*2**(n-1),8e3):250*2**(n-1)}function N(r,n){const s=`${n?.modell??""}\0${n?.geduld??"kurz"}\0${r}`,c=Date.now(),e=l.get(s);if(e&&e.bis>c)return e.vektor;const o=T(r,n);if(l.set(s,{bis:c+P,vektor:o}),l.size>v){const t=l.keys().next().value;t!==void 0&&l.delete(t)}return o.catch(()=>{l.get(s)?.vektor===o&&l.delete(s)}),o}const P=6e4,v=200,l=new Map;function Y(){l.clear()}async function T(r,n){const s=n?.geduld??"kurz";if(n?.modell&&d!=="cachly"&&d!=="ollama")throw new Error(`Anbieter "${d}" kann kein abweichendes Modell anfragen (verlangt: ${n.modell}).`);let c=0;for(;;){c++;try{A(`einbettung: Anfang (${r.length} Zeichen, Versuch ${c})`);const e=await y(r,s,n?.modell);return A("einbettung: fertig"),e}catch(e){const o=O(e,c,s);if(o===null)throw e;await new Promise(t=>setTimeout(t,o))}}}function k(){switch(d){case"cachly":return!!i.jwt;case"mistral":return!!process.env.MISTRAL_API_KEY;case"cohere":return!!process.env.COHERE_API_KEY;case"ollama":return!0;case"gemini":return!!process.env.GEMINI_API_KEY;case"openai":return!!process.env.OPENAI_API_KEY;case"none":return!1;default:return!1}}function D(){const r={cachly:"CACHLY_JWT (server-side, no extra key needed)",openai:"OPENAI_API_KEY",mistral:"MISTRAL_API_KEY",cohere:"COHERE_API_KEY",ollama:"OLLAMA_BASE_URL (optional, default: http://localhost:11434)",gemini:"GEMINI_API_KEY"};if(d==="none")return"No embedding provider configured. Sign in (CACHLY_JWT) to use the EU-hosted cachly embeddings, or set OLLAMA_BASE_URL for a local model. Brain works without embedding.";const n=r[d]??"CACHLY_JWT";return`CACHLY_EMBED_PROVIDER=${d} \u2192 requires ${n}`}export{d as EMBED_PROVIDER,N as computeEmbedding,i as embedConfig,D as embedProviderHint,k as hasEmbedProvider,M as istVoruebergehend,R as setEmbedJwt,Y as vergissEinbettungen,O as wiederholungMs,f as zeitlimitMs};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function l(
|
|
2
|
-
`),
|
|
3
|
-
`).trim()||null}function
|
|
4
|
-
`)}export{l as extractFirstRecallProof,s as renderFirstRecallProof};
|
|
1
|
+
function l(t){if(!t)return null;const r=t.split(`
|
|
2
|
+
`),e=r.findIndex(n=>/first recall already works/i.test(n));if(e===-1)return null;const i=[];for(let n=e;n<r.length&&!(n>e&&r[n].trim()==="");n++)i.push(r[n]);return i.join(`
|
|
3
|
+
`).trim()||null}function c(t,r){const e=r.trim();return["\u{1F3AF} Proof \u2014 your first recall already works.",` Top hit: ${t} \u2014 ${e}`].join(`
|
|
4
|
+
`)}function s(t){if(!t)return null;const r=/\*\*💡\s+([^*]+)\*\*/.exec(t);if(!r)return null;const e=t.slice(r.index+r[0].length),i=/^>\s+(.+)$/m.exec(e);if(!i)return null;const o=r[1].trim(),n=i[1].trim();return!o||!n?null:{topic:o,what:n}}function u(t){return t.replace(/\*\*/g,"").replace(/`/g,"")}export{l as extractFirstRecallProof,s as extractTopHit,u as fuersTerminal,c as renderFirstRecallProof};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as r}from"node:crypto";function a(t){return`cachly:brain_from_git:last_sha:${r("sha256").update(t).digest("hex").slice(0,32)}`}function s(t){return`cachly:brain_from_git:last_sha:${Buffer.from(t).toString("base64").slice(0,32)}`}export{s as alterStartpunktSchluessel,a as startpunktSchluessel};
|
|
@@ -3,10 +3,10 @@ import{ckgSlug as j}from"../ckg.js";import{safeJsonParse as x,darfHeraus as N}fr
|
|
|
3
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
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:best:*","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
|
|
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 in ${e.recall_count??0} answers`),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
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
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($)},"
|
|
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($)},"the instruction file (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
|
|