@cachly-dev/mcp-server 0.10.207 → 0.10.208
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/src/editor-mcp-eintrag.js +10 -0
- package/dist/src/index.js +149 -150
- package/dist/src/uninstall.js +6 -6
- package/glama.json +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/src/uninstall.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import{existsSync as
|
|
1
|
+
import{existsSync as A,lstatSync as R,readFileSync as Z,readdirSync as v,rmSync as x,rmdirSync as ee,writeFileSync as te}from"node:fs";import{basename as b,dirname as C,isAbsolute as T,join as g,relative as I,resolve as k,sep as S}from"node:path";import{ANWEISUNGS_DATEIEN as ne,CLAUDE_MD_MARKER_END as H,CLAUDE_MD_MARKER_START as D,EDITOR_FILES as re,blockMuster as oe}from"./projektdateien.js";import{PROJEKT_HOOK_MARKE as $,istCachlyEintrag as N}from"./hook-zugang.js";import{CLS_BLOCK_RE as se}from"./cls-hook.js";import{BRAIN_WATCH_BLOCK_RE as ie}from"./brain-watch-hook.js";import{CLAUDE_HOOK_DIR as ae,CLAUDE_SETTINGS_DATEI as ce,CODEX_HOOKS_DATEI as le,CODEX_HOOK_DIR as he,COPILOT_HOOKS_DATEI as ue,COPILOT_HOOK_DIR as fe,CURSOR_HOOKS_DATEI as de,CURSOR_HOOK_DIR as pe,GEMINI_HOOK_DIR as me,GEMINI_SETTINGS_DATEI as z}from"./ambient-hooks.js";import{CURSOR_ABLAGE_ORDNER as ge}from"./cursor-hook.js";import{CODEX_CONFIG_DATEI as ye,ohneCodexMcpEintrag as ke}from"./editor-mcp-eintrag.js";import{COPILOT_ABLAGE_ORDNER as be}from"./copilot-hook.js";import{credentialsPath as P}from"./credentials.js";import{defaultLedgerPath as M,readLedger as ve}from"./ambient-ledger.js";import{defaultMilestonePath as je}from"./funnel-milestones.js";import{defaultKostprobePath as we}from"./kostprobe.js";import{standPfad as _e}from"./neue-fassung.js";import{AUFTRAG as Ee,FEHLSCHLAG as Oe,SPERRE as Se}from"./konto-anlegen.js";import{netBalance as $e}from"./ambient-recall.js";import{istTestSchluessel as Ae}from"./uebernahme.js";const Re='broken Stop hook from setup_ai_memory ("checkpoint" is not a command)',B="Your lessons stay in your cachly account. uninstall never deletes cloud data. To erase your account and everything in it (GDPR Art. 17), write to privacy@cachly.dev (https://cachly.dev/legal/datenschutz).",xe=[P({home:""}),M(),je(),we(),_e(""),Se,Oe,Ee].map(t=>b(t));function Ce(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}const Te=new RegExp(`^(?:${xe.map(Ce).join("|")})(?:\\.[\\w.-]*(?:tmp|genommen))?$`),Ie=/^cachly-(?:ambient|leser-sicherung|lernen-arme|projektversionen|startwissen-import)-[\w.-]+\.(?:json|jsonl|lock|tmp)$/,He=["cachly-lernen",b(ge),b(be)];function De(t,e){return e?He.includes(t):Ie.test(t)}function p(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}function L(t){try{const e=JSON.parse(t);return p(e)?e:null}catch{return null}}function K(t,e){const n=/^([ \t]+)"/m.exec(e)?.[1]??2,r=e.includes(`\r
|
|
2
2
|
`);let o=JSON.stringify(t,null,n);return r&&(o=o.replace(/\n/g,`\r
|
|
3
3
|
`)),/\n$/.test(e)?o+(r?`\r
|
|
4
4
|
`:`
|
|
5
|
-
`):o}function y(t){try{return
|
|
5
|
+
`):o}function y(t){try{return R(t).isFile()?Z(t,"utf8"):null}catch{return null}}function F(t){try{return R(t).isDirectory()}catch{return!1}}function Ne(t){if(!p(t))return"";const n=(p(t.env)?t.env:p(t.command)&&p(t.command.env)?t.command.env:null)?.CACHLY_BRAIN_INSTANCE_ID;return typeof n=="string"?n:""}function j(t,e,n){const r=t[e];return!p(r)||!("cachly"in r)?!1:(n.push(r.cachly),delete r.cachly,Object.keys(r).length===0&&delete t[e],!0)}function G(t){return p(t)?p(t.env)&&("CACHLY_JWT"in t.env||"CACHLY_BRAIN_INSTANCE_ID"in t.env)?!0:JSON.stringify(t).includes("@cachly-dev/mcp-server"):!1}function w(t,e){const n=L(t);if(!n)return{art:"unlesbar"};const r=[],o=[];if(e==="mcpServers"&&j(n,"mcpServers",r)&&o.push("mcpServers.cachly"),e==="vscode"&&(j(n,"servers",r)&&o.push("servers.cachly"),j(n,"mcpServers",r)&&o.push("mcpServers.cachly")),e==="zed"&&j(n,"context_servers",r)&&o.push("context_servers.cachly"),e==="continue"){const a=n.experimental,c=p(a)?a.modelContextProtocolServers:void 0;if(p(a)&&Array.isArray(c)){const s=c.filter(l=>!G(l));s.length<c.length&&(r.push(...c.filter(G)),o.push(`experimental.modelContextProtocolServers (${c.length-s.length})`),s.length===0?delete a.modelContextProtocolServers:a.modelContextProtocolServers=s,Object.keys(a).length===0&&delete n.experimental)}}if(o.length===0)return{art:"nichts"};const i=r.map(Ne).find(Boolean)??"";return{art:"geaendert",nachher:Object.keys(n).length===0?null:K(n,t),entfernt:o,instanz:i}}function ze(t){if(N(t))return"ambient";const e=String(t?.command??"");return e.includes("@cachly-dev/mcp-server")&&e.includes(" checkpoint")?"checkpoint":null}function _(t){return N(t)?"ambient":null}function U(t,e,n=[]){const r=L(t);if(!r)return{art:"unlesbar"};const o=r.hooks;if(!p(o))return{art:"nichts"};const i=[];for(const[c,s]of Object.entries(o)){if(!Array.isArray(s))continue;const l=i.length,h=[];for(const u of s){const d=p(u)&&Array.isArray(u.hooks)?u.hooks:null;if(!d){const f=e(u);f?i.push(f):h.push(u);continue}const m=d.filter(f=>{const O=e(f);return O&&i.push(O),!O});m.length===d.length?h.push(u):m.length>0&&h.push({...u,hooks:m})}i.length!==l&&(h.length===0?delete o[c]:o[c]=h)}return i.length===0?{art:"nichts"}:(Object.keys(o).length===0&&delete r.hooks,{art:"geaendert",nachher:Object.keys(r).filter(c=>!n.includes(c)).length===0?null:K(r,t),entfernt:i,instanz:""})}function Pe(t,e,n){let r=e;t[e-1]===`
|
|
6
6
|
`&&(r=t[e-2]==="\r"?e-2:e-1);let o=n;return t[n]===`
|
|
7
7
|
`?o=n+1:t[n]==="\r"&&t[n+1]===`
|
|
8
8
|
`&&(o=n+2),r<e&&o>n&&r>0&&o<t.length&&t[r-1]!==`
|
|
9
9
|
`&&t[o]!==`
|
|
10
|
-
`&&t[o]!=="\r"&&(o=n),t.slice(0,r)+t.slice(o)}function
|
|
10
|
+
`&&t[o]!=="\r"&&(o=n),t.slice(0,r)+t.slice(o)}function Me(t){if(!t.includes(D)&&!t.includes(H))return{art:"kein-block"};let e=t,n=0;for(;;){const r=oe().exec(e);if(!r)break;e=Pe(e,r.index,r.index+r[0].length),n++}return n===0||e.includes(D)||e.includes(H)?{art:"kaputt"}:{art:"entfernt",rest:e}}function Be(t){const e=t.trim().split(/\r?\n/);if(e[0]?.trim()!=="---")return!1;const n=e.findIndex((r,o)=>o>0&&r.trim()==="---");return n>0&&e.slice(n+1).every(r=>r.trim()==="")}function Le(t,e){return t.trim()===""||e&&Be(t)}function Ke(t){let e=t;const n=[],r=[["CLS hook",se],["brain_watch hook",ie]];for(const[i,a]of r)for(;;){const c=a.exec(e);if(!c)break;const s=e.slice(0,c.index).replace(/\s+$/,""),l=e.slice(c.index+c[0].length).replace(/^\s*\n/,"");e=s+(s&&l.trim()?`
|
|
11
11
|
|
|
12
12
|
`:"")+l,n.push(i)}if(n.length===0)return{rest:t,entfernt:n};const o=e.trim();return o===""||o.startsWith("#!")&&!o.includes(`
|
|
13
13
|
`)?{rest:"",entfernt:n}:{rest:e.replace(/\s+$/,"")+`
|
|
14
|
-
`,entfernt:n}}function Me(t,e){const n=H(e,t);return n!==""&&!n.startsWith("..")&&!I(n)}function G(t,e,n,r){const o=new Set(t.filter(a=>a.stufe===e&&(a.aktion==="datei-loeschen"||a.aktion==="ordner-loeschen")).map(a=>a.pfad)),i=new Set;for(const a of o)for(let s=T(a);s!==r&&Me(s,n)&&!s.split(S).includes(".git");s=T(s))i.add(s);const c=[];for(const a of[...i].sort((s,l)=>l.length-s.length)){let s;try{s=j(a)}catch{continue}s.every(l=>o.has(g(a,l)))&&(o.add(a),c.push({stufe:e,aktion:"ordner-entfernen",pfad:a,was:"empty folder"}))}return c}function Ke(t,e){const n=new Map;for(const[r,o]of Object.entries(ne))n.set(o,r==="continue"?"continue":r==="zed"?"zed":o===".vscode/mcp.json"?"vscode":"mcpServers");for(const[r,o]of n){const i=k(t.projekt,r),c=y(i);if(R(`${i}.bak`)&&e.funde.push({stufe:"projekt",aktion:"melden",pfad:`${i}.bak`,was:"your old file is there; uninstall does not restore it"}),c===null)continue;const a=A(c,o);if(a.art==="unlesbar"){c.includes("cachly")&&e.vonHand.push({stufe:"projekt",text:`${r}: cannot be read as plain JSON (comments or another format). Remove the "cachly" entry by hand.`});continue}a.art!=="nichts"&&(e.instanz||=a.instanz,a.nachher===null?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:i,was:'MCP server entry "cachly", the only thing in the file',vorher:c}):e.funde.push({stufe:"projekt",aktion:"eintrag-entfernen",pfad:i,was:'MCP server entry "cachly"; other servers and settings stay',vorher:c,nachher:a.nachher}))}}function Fe(t,e){for(const n of te){const r=k(t.projekt,...n.pfad),o=y(r);if(o===null)continue;const i=n.pfad.join("/"),c=ze(o);if(c.art==="kein-block"){o.startsWith("# cachly AI Brain")&&e.vonHand.push({stufe:"projekt",text:`${i}: looks like the whole file was written by the setup_ai_memory tool (no markers). Check it and remove it by hand if it is not yours.`});continue}if(c.art==="kaputt"){e.vonHand.push({stufe:"projekt",text:`${i}: a cachly marker has no partner. Remove the block by hand.`});continue}Be(c.rest,i.endsWith(".mdc"))?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:r,was:"only the cachly block was in it",vorher:o}):e.funde.push({stufe:"projekt",aktion:"block-entfernen",pfad:r,was:"cachly block between the markers; your text stays as it is",vorher:o,nachher:c.rest})}}function v(t,e,n,r,o){const i=k(t.projekt,n),c=y(i);if(c===null)return;const a=De(c,r,o);if(a.art==="unlesbar"){(c.includes(z)||c.includes("@cachly-dev/mcp-server"))&&e.vonHand.push({stufe:"projekt",text:`${n}: cannot be read as plain JSON (comments or another format). Remove the cachly hooks by hand.`});return}if(a.art==="nichts")return;const s=a.entfernt.filter(u=>u==="ambient").length,l=a.entfernt.filter(u=>u==="checkpoint").length,h=[...s?[`${s} Ambient Recall hook${s===1?"":"s"}`]:[],...l?[`${l} ${Oe}`]:[]];a.nachher===null?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:i,was:`${h.join(" and ")}, the only thing in the file`,vorher:c}):e.funde.push({stufe:"projekt",aktion:"eintrag-entfernen",pfad:i,was:`${h.join(" and ")}; other hooks and settings stay`,vorher:c,nachher:a.nachher})}function Ue(t,e,n){const r=k(t.projekt,n);let o;try{o=j(r)}catch{return}for(const i of o.sort()){const c=g(r,i);!i.startsWith(z)||y(c)===null||e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:c,was:"Ambient Recall hook script"})}}function Ge(t,e){v(t,e,ae,He,[]),v(t,e,fe,_,["version"]),v(t,e,he,_,["version"]),v(t,e,ce,_,[]),v(t,e,O,_,[]);for(const r of[ie,de,ue,le,pe])Ue(t,e,r);const n=$(y(k(t.projekt,O))??"");n&&p(n.mcpServers)&&"cachly"in n.mcpServers&&e.vonHand.push({stufe:"projekt",text:`${O}: the MCP server "cachly" (added by "gemini mcp add") stays. Remove that entry by hand.`})}function We(t,e){const n=g(t.projekt,".git");if(!R(n))return;if(!F(n)){e.vonHand.push({stufe:"projekt",text:".git is a file here (a Git worktree). cachly never writes a post-commit hook there. If you set one up in the main repository, check its .git/hooks/post-commit."});return}const r=g(n,"hooks","post-commit"),o=y(r);if(o===null)return;const i=Le(o);if(i.entfernt.length===0)return;const c=i.entfernt.join(" and ");i.rest===""?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:r,was:`${c}, the only thing in the hook`,vorher:o}):e.funde.push({stufe:"projekt",aktion:"block-entfernen",pfad:r,was:`${c}; your own commands stay`,vorher:o,nachher:i.rest})}function Je(t,e){const n=g(t.heim,".claude","mcp.json"),r=y(n);if(r!==null){const s=A(r,"mcpServers");s.art==="unlesbar"&&r.includes("cachly")?e.vonHand.push({stufe:"global",text:'~/.claude/mcp.json: cannot be read as plain JSON. Remove the "cachly" entry by hand.'}):s.art==="geaendert"&&(e.instanz||=s.instanz,s.nachher===null?e.funde.push({stufe:"global",aktion:"datei-loeschen",pfad:n,was:'MCP server entry "cachly", the only thing in the file (it holds your key)',vorher:r}):e.funde.push({stufe:"global",aktion:"eintrag-entfernen",pfad:n,was:'MCP server entry "cachly" (it holds your key); other servers stay',vorher:r,nachher:s.nachher}))}for(const s of[g(t.heim,".cursor","mcp.json"),g(t.heim,".codeium","windsurf","mcp_config.json")]){const l=y(s);if(l===null)continue;const h=A(l,"mcpServers");(h.art==="geaendert"||h.art==="unlesbar"&&l.includes("cachly"))&&e.funde.push({stufe:"global",aktion:"melden",pfad:s,was:'has a "cachly" server entry. You set this file up yourself, so uninstall leaves it. Remove the entry by hand.'})}const o=g(t.heim,".cachly");let i=[];try{i=j(o)}catch{}const c=[];for(const s of i.sort()){const l=g(o,s);if(Re.test(s)&&y(l)!==null){const h=s===b(B({home:""}))?"your key and Brain id; other projects on this computer lose their access":"cachly data on this computer";e.funde.push({stufe:"global",aktion:"datei-loeschen",pfad:l,was:h})}else c.push(s)}c.length>0&&e.vonHand.push({stufe:"global",text:`~/.cachly also holds ${c.join(", ")}. Not written by this package, so it stays.${c.includes("vscode-mcp.env")?" vscode-mcp.env holds your key (written by the VS Code extension): uninstall the extension, then delete it.":""}`});let a=[];try{a=j(t.tmp)}catch{}for(const s of a.sort()){if(!s.startsWith("cachly-"))continue;const l=g(t.tmp,s),h=F(l);Te(s,h)&&e.funde.push({stufe:"global",aktion:h?"ordner-loeschen":"datei-loeschen",pfad:l,was:"cache in the temp folder"})}}function Ye(t){const e={projekt:k(t.projekt),heim:k(t.heim),tmp:k(t.tmp)},n={funde:[],vonHand:[],instanz:""};return Ke(e,n),Fe(e,n),Ge(e,n),We(e,n),Je(e,n),n.funde.push(...G(n.funde,"projekt",e.projekt,e.tmp)),n.funde.push(...G(n.funde,"global",e.heim,e.tmp)),n}function W(t){return t.split(S).length}function J(t){return[...t].sort((n,r)=>{const o=i=>i.aktion==="ordner-entfernen"?1:0;return o(n)-o(r)||(o(n)?W(r.pfad)-W(n.pfad):0)}).map(n=>{if(n.aktion==="melden")return{fund:n,status:"uebersprungen",grund:"only reported"};try{return n.vorher!==void 0&&y(n.pfad)!==n.vorher?{fund:n,status:"uebersprungen",grund:"the file changed after the plan was made"}:(n.aktion==="datei-loeschen"?C(n.pfad,{force:!0}):n.aktion==="ordner-loeschen"?C(n.pfad,{recursive:!0,force:!0}):n.aktion==="ordner-entfernen"?Z(n.pfad):ee(n.pfad,n.nachher??"","utf8"),{fund:n,status:"entfernt"})}catch(r){const o=r.code==="ENOTEMPTY"?"the folder is not empty":r.message;return{fund:n,status:"uebersprungen",grund:o}}})}async function Ve(t){const e=await ye(g(t.heim,".cachly",b(L()))),n=Ee(e),r={schluessel:t.schluessel?Se(t.schluessel)?"test":"konto":"keiner",turns:e.length,injected:n.injected,prevented:n.prevented,net:n.net,lektionen:null};if(!t.schluessel||!t.instanz)return r.lektionenFehlt="no-instance",r;try{const o=await(t.fetchFn??fetch)(`${t.apiUrl}/api/v1/instances/${t.instanz}/memory`,{headers:{Authorization:`Bearer ${t.schluessel}`},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`HTTP ${o.status}`);const i=(await o.json()).lesson_count;if(typeof i!="number")throw new Error("no lesson_count");r.lektionen=i}catch{r.lektionenFehlt="unreachable"}return r}const Xe={"datei-loeschen":"delete file","ordner-loeschen":"delete folder","ordner-entfernen":"remove folder","eintrag-entfernen":"remove entry","block-entfernen":"remove block",melden:"note only"};function Y(t,e){const n=t.stufe==="projekt"?e.projekt:e.heim,r=H(n,t.pfad),o=r!==""&&!r.startsWith("..")&&!I(r),i=(o?r:t.pfad).split(S).join("/");return t.stufe==="global"&&o?`~/${i}`:i}function qe(t,e){const n=e.ausgabe;n(""),n("What you have right now");const r=t.schluessel==="test"?"test key (cky_trial_), the Brain behind it is a test Brain":t.schluessel==="konto"?"account key":"none found";n(` Key: ${r}`);const o=t.lektionen!==null?`${t.lektionen} in your Brain`:t.lektionenFehlt==="no-instance"?"unknown (no key or Brain found here)":"not reachable right now";n(` Lessons: ${o}`),n(t.turns>0?` Ledger: ${t.turns} turns, ${t.injected} tokens injected, ${t.prevented} prevented, net ${t.net>=0?"+":""}${t.net} tokens`:" Ledger: no turns recorded"),n(" To keep your lessons first, write them to disk:"),n(" npx @cachly-dev/mcp-server@latest export")}function V(t,e,n){n.ausgabe(""),n.ausgabe(t);for(const r of e)n.ausgabe(` ${Xe[r.aktion].padEnd(14)} ${Y(r,n)} (${r.was})`)}function X(t,e,n){n.ausgabe(""),n.ausgabe("By hand (uninstall cannot do these):"),n.ausgabe(" - Codex and Gemini CLI keep the cachly MCP server in their own settings (~/.codex/config.toml, .gemini/settings.json). If you registered it there, remove the entry named cachly."),n.ausgabe(' - Uninstall the JetBrains plugin "Cachly Brain" (Settings, Plugins) and the VS Code extension "cachly Brain" (cachly-dev.cachly-brain), if you installed them.');for(const r of t.vonHand)(r.stufe==="projekt"||e)&&n.ausgabe(` - ${r.text}`)}function q(t,e){e.ausgabe("");for(const r of t){if(r.fund.aktion==="melden")continue;const o=r.status==="entfernt"?"removed":"skipped";e.ausgabe(` ${o.padEnd(8)} ${Y(r.fund,e)}${r.grund?` (${r.grund})`:""}`)}const n=t.filter(r=>r.fund.aktion!=="melden");e.ausgabe(`Done: ${n.filter(r=>r.status==="entfernt").length} removed, ${n.filter(r=>r.status==="uebersprungen").length} skipped.`)}function Qe(t){return{dryRun:t.includes("--dry-run"),ja:t.includes("--yes")||t.includes("-y"),global:t.includes("--global")}}async function gt(t,e){const n=Qe(t),r=Ye({projekt:e.projekt,heim:e.heim,tmp:e.tmp}),o=await Ve({heim:e.heim,schluessel:e.schluessel,instanz:e.instanz||r.instanz,apiUrl:e.apiUrl,fetchFn:e.fetchFn});qe(o,e);const i=r.funde.filter(d=>d.stufe==="projekt"),c=r.funde.filter(d=>d.stufe==="global"),a=i.filter(d=>d.aktion!=="melden"),s=c.filter(d=>d.aktion!=="melden");if(i.length===0&&(!n.global||c.length===0))return e.ausgabe(""),e.ausgabe(`Nothing found in ${e.projekt}${n.global?" or your home folder":""}: cachly has not written anything here that uninstall can remove.`),!n.global&&s.length>0&&e.ausgabe(`Your home folder still holds ${s.length} cachly files (key, ledger, caches). "uninstall --global" removes them.`),X(r,n.global,e),e.ausgabe(""),e.ausgabe(M),0;if(i.length>0&&V(`In this project (${e.projekt}):`,i,e),n.global&&c.length>0&&V("In your home folder and temp folder (--global):",c,e),X(r,n.global,e),e.ausgabe(""),e.ausgabe(M),n.dryRun)return e.ausgabe(""),e.ausgabe("Dry run: nothing was changed."),!n.global&&s.length>0&&e.ausgabe(`Your home and temp folders hold ${s.length} more cachly files (key, ledger, caches); add --global to include them.`),0;if(!(a.length>0||n.global&&s.length>0))return e.ausgabe(""),e.ausgabe("Nothing to remove."),0;if(!n.ja&&!e.istTty)return e.ausgabe(""),e.ausgabe('This is not a terminal and --yes is missing: nothing was changed. Run it in a terminal, or add --yes. "--dry-run" only shows the plan.'),1;let h=0,u=0;if(a.length>0)if(n.ja||await e.frage(`
|
|
15
|
-
Remove these ${
|
|
16
|
-
Remove these ${s.length} items from your home and temp folder? [y/N] `)){const m=
|
|
14
|
+
`,entfernt:n}}function Fe(t,e){const n=I(e,t);return n!==""&&!n.startsWith("..")&&!T(n)}function W(t,e,n,r){const o=new Set(t.filter(c=>c.stufe===e&&(c.aktion==="datei-loeschen"||c.aktion==="ordner-loeschen")).map(c=>c.pfad)),i=new Set;for(const c of o)for(let s=C(c);s!==r&&Fe(s,n)&&!s.split(S).includes(".git");s=C(s))i.add(s);const a=[];for(const c of[...i].sort((s,l)=>l.length-s.length)){let s;try{s=v(c)}catch{continue}s.every(l=>o.has(g(c,l)))&&(o.add(c),a.push({stufe:e,aktion:"ordner-entfernen",pfad:c,was:"empty folder"}))}return a}function Ge(t,e){const n=new Map;for(const[r,o]of Object.entries(re))n.set(o,r==="continue"?"continue":r==="zed"?"zed":o===".vscode/mcp.json"?"vscode":"mcpServers");for(const[r,o]of n){const i=k(t.projekt,r),a=y(i);if(A(`${i}.bak`)&&e.funde.push({stufe:"projekt",aktion:"melden",pfad:`${i}.bak`,was:"your old file is there; uninstall does not restore it"}),a===null)continue;const c=w(a,o);if(c.art==="unlesbar"){a.includes("cachly")&&e.vonHand.push({stufe:"projekt",text:`${r}: cannot be read as plain JSON (comments or another format). Remove the "cachly" entry by hand.`});continue}c.art!=="nichts"&&(e.instanz||=c.instanz,c.nachher===null?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:i,was:'MCP server entry "cachly", the only thing in the file',vorher:a}):e.funde.push({stufe:"projekt",aktion:"eintrag-entfernen",pfad:i,was:'MCP server entry "cachly"; other servers and settings stay',vorher:a,nachher:c.nachher}))}}function Ue(t,e){for(const n of ne){const r=k(t.projekt,...n.pfad),o=y(r);if(o===null)continue;const i=n.pfad.join("/"),a=Me(o);if(a.art==="kein-block"){o.startsWith("# cachly AI Brain")&&e.vonHand.push({stufe:"projekt",text:`${i}: looks like the whole file was written by the setup_ai_memory tool (no markers). Check it and remove it by hand if it is not yours.`});continue}if(a.art==="kaputt"){e.vonHand.push({stufe:"projekt",text:`${i}: a cachly marker has no partner. Remove the block by hand.`});continue}Le(a.rest,i.endsWith(".mdc"))?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:r,was:"only the cachly block was in it",vorher:o}):e.funde.push({stufe:"projekt",aktion:"block-entfernen",pfad:r,was:"cachly block between the markers; your text stays as it is",vorher:o,nachher:a.rest})}}function E(t,e,n,r,o){const i=k(t.projekt,n),a=y(i);if(a===null)return;const c=U(a,r,o);if(c.art==="unlesbar"){(a.includes($)||a.includes("@cachly-dev/mcp-server"))&&e.vonHand.push({stufe:"projekt",text:`${n}: cannot be read as plain JSON (comments or another format). Remove the cachly hooks by hand.`});return}if(c.art==="nichts")return;const s=c.entfernt.filter(u=>u==="ambient").length,l=c.entfernt.filter(u=>u==="checkpoint").length,h=[...s?[`${s} Ambient Recall hook${s===1?"":"s"}`]:[],...l?[`${l} ${Re}`]:[]];c.nachher===null?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:i,was:`${h.join(" and ")}, the only thing in the file`,vorher:a}):e.funde.push({stufe:"projekt",aktion:"eintrag-entfernen",pfad:i,was:`${h.join(" and ")}; other hooks and settings stay`,vorher:a,nachher:c.nachher})}function We(t,e,n){const r=k(t.projekt,n);let o;try{o=v(r)}catch{return}for(const i of o.sort()){const a=g(r,i);!i.startsWith($)||y(a)===null||e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:a,was:"Ambient Recall hook script"})}}function Je(t,e){E(t,e,ce,ze,[]),E(t,e,de,_,["version"]),E(t,e,ue,_,["version"]),E(t,e,le,_,[]),Ye(t,e);for(const n of[ae,pe,fe,he,me])We(t,e,n);Ve(t,e)}function Ye(t,e){const n=k(t.projekt,z),r=y(n);if(r===null)return;const o=U(r,_,[]);if(o.art==="unlesbar"){(r.includes($)||r.includes("@cachly-dev/mcp-server"))&&e.vonHand.push({stufe:"projekt",text:`${z}: cannot be read as plain JSON (comments or another format). Remove the cachly hooks and the MCP server "cachly" by hand.`});return}const i=o.art==="geaendert"?o.nachher:r,a=i===null?{art:"nichts"}:w(i,"mcpServers"),c=a.art==="geaendert"?a.nachher:i;if(o.art!=="geaendert"&&a.art!=="geaendert")return;a.art==="geaendert"&&(e.instanz||=a.instanz);const s=o.art==="geaendert"?o.entfernt.length:0,l=[...s?[`${s} Ambient Recall hook${s===1?"":"s"}`]:[],...a.art==="geaendert"?['MCP server entry "cachly"']:[]];c===null?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:n,was:`${l.join(" and ")}, the only thing in the file`,vorher:r}):e.funde.push({stufe:"projekt",aktion:"eintrag-entfernen",pfad:n,was:`${l.join(" and ")}; other servers, hooks and settings stay`,vorher:r,nachher:c})}function Ve(t,e){const n=k(t.projekt,ye),r=y(n);if(r===null)return;const o=ke(r);o.entfernt&&(o.rest===""?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:n,was:"MCP server table [mcp_servers.cachly], the only thing in the file",vorher:r}):e.funde.push({stufe:"projekt",aktion:"eintrag-entfernen",pfad:n,was:"MCP server table [mcp_servers.cachly]; other settings stay",vorher:r,nachher:o.rest}))}function Xe(t,e){const n=g(t.projekt,".git");if(!A(n))return;if(!F(n)){e.vonHand.push({stufe:"projekt",text:".git is a file here (a Git worktree). cachly never writes a post-commit hook there. If you set one up in the main repository, check its .git/hooks/post-commit."});return}const r=g(n,"hooks","post-commit"),o=y(r);if(o===null)return;const i=Ke(o);if(i.entfernt.length===0)return;const a=i.entfernt.join(" and ");i.rest===""?e.funde.push({stufe:"projekt",aktion:"datei-loeschen",pfad:r,was:`${a}, the only thing in the hook`,vorher:o}):e.funde.push({stufe:"projekt",aktion:"block-entfernen",pfad:r,was:`${a}; your own commands stay`,vorher:o,nachher:i.rest})}function qe(t,e){const n=g(t.heim,".claude","mcp.json"),r=y(n);if(r!==null){const s=w(r,"mcpServers");s.art==="unlesbar"&&r.includes("cachly")?e.vonHand.push({stufe:"global",text:'~/.claude/mcp.json: cannot be read as plain JSON. Remove the "cachly" entry by hand.'}):s.art==="geaendert"&&(e.instanz||=s.instanz,s.nachher===null?e.funde.push({stufe:"global",aktion:"datei-loeschen",pfad:n,was:'MCP server entry "cachly", the only thing in the file (it holds your key)',vorher:r}):e.funde.push({stufe:"global",aktion:"eintrag-entfernen",pfad:n,was:'MCP server entry "cachly" (it holds your key); other servers stay',vorher:r,nachher:s.nachher}))}for(const s of[g(t.heim,".cursor","mcp.json"),g(t.heim,".codeium","windsurf","mcp_config.json")]){const l=y(s);if(l===null)continue;const h=w(l,"mcpServers");(h.art==="geaendert"||h.art==="unlesbar"&&l.includes("cachly"))&&e.funde.push({stufe:"global",aktion:"melden",pfad:s,was:'has a "cachly" server entry. You set this file up yourself, so uninstall leaves it. Remove the entry by hand.'})}const o=g(t.heim,".cachly");let i=[];try{i=v(o)}catch{}const a=[];for(const s of i.sort()){const l=g(o,s);if(Te.test(s)&&y(l)!==null){const h=s===b(P({home:""}))?"your key and Brain id; other projects on this computer lose their access":"cachly data on this computer";e.funde.push({stufe:"global",aktion:"datei-loeschen",pfad:l,was:h})}else a.push(s)}a.length>0&&e.vonHand.push({stufe:"global",text:`~/.cachly also holds ${a.join(", ")}. Not written by this package, so it stays.${a.includes("vscode-mcp.env")?" vscode-mcp.env holds your key (written by the VS Code extension): uninstall the extension, then delete it.":""}`});let c=[];try{c=v(t.tmp)}catch{}for(const s of c.sort()){if(!s.startsWith("cachly-"))continue;const l=g(t.tmp,s),h=F(l);De(s,h)&&e.funde.push({stufe:"global",aktion:h?"ordner-loeschen":"datei-loeschen",pfad:l,was:"cache in the temp folder"})}}function Qe(t){const e={projekt:k(t.projekt),heim:k(t.heim),tmp:k(t.tmp)},n={funde:[],vonHand:[],instanz:""};return Ge(e,n),Ue(e,n),Je(e,n),Xe(e,n),qe(e,n),n.funde.push(...W(n.funde,"projekt",e.projekt,e.tmp)),n.funde.push(...W(n.funde,"global",e.heim,e.tmp)),n}function J(t){return t.split(S).length}function Y(t){return[...t].sort((n,r)=>{const o=i=>i.aktion==="ordner-entfernen"?1:0;return o(n)-o(r)||(o(n)?J(r.pfad)-J(n.pfad):0)}).map(n=>{if(n.aktion==="melden")return{fund:n,status:"uebersprungen",grund:"only reported"};try{return n.vorher!==void 0&&y(n.pfad)!==n.vorher?{fund:n,status:"uebersprungen",grund:"the file changed after the plan was made"}:(n.aktion==="datei-loeschen"?x(n.pfad,{force:!0}):n.aktion==="ordner-loeschen"?x(n.pfad,{recursive:!0,force:!0}):n.aktion==="ordner-entfernen"?ee(n.pfad):te(n.pfad,n.nachher??"","utf8"),{fund:n,status:"entfernt"})}catch(r){const o=r.code==="ENOTEMPTY"?"the folder is not empty":r.message;return{fund:n,status:"uebersprungen",grund:o}}})}async function Ze(t){const e=await ve(g(t.heim,".cachly",b(M()))),n=$e(e),r={schluessel:t.schluessel?Ae(t.schluessel)?"test":"konto":"keiner",turns:e.length,injected:n.injected,prevented:n.prevented,net:n.net,lektionen:null};if(!t.schluessel||!t.instanz)return r.lektionenFehlt="no-instance",r;try{const o=await(t.fetchFn??fetch)(`${t.apiUrl}/api/v1/instances/${t.instanz}/memory`,{headers:{Authorization:`Bearer ${t.schluessel}`},signal:AbortSignal.timeout(5e3)});if(!o.ok)throw new Error(`HTTP ${o.status}`);const i=(await o.json()).lesson_count;if(typeof i!="number")throw new Error("no lesson_count");r.lektionen=i}catch{r.lektionenFehlt="unreachable"}return r}const et={"datei-loeschen":"delete file","ordner-loeschen":"delete folder","ordner-entfernen":"remove folder","eintrag-entfernen":"remove entry","block-entfernen":"remove block",melden:"note only"};function V(t,e){const n=t.stufe==="projekt"?e.projekt:e.heim,r=I(n,t.pfad),o=r!==""&&!r.startsWith("..")&&!T(r),i=(o?r:t.pfad).split(S).join("/");return t.stufe==="global"&&o?`~/${i}`:i}function tt(t,e){const n=e.ausgabe;n(""),n("What you have right now");const r=t.schluessel==="test"?"test key (cky_trial_), the Brain behind it is a test Brain":t.schluessel==="konto"?"account key":"none found";n(` Key: ${r}`);const o=t.lektionen!==null?`${t.lektionen} in your Brain`:t.lektionenFehlt==="no-instance"?"unknown (no key or Brain found here)":"not reachable right now";n(` Lessons: ${o}`),n(t.turns>0?` Ledger: ${t.turns} turns, ${t.injected} tokens injected, ${t.prevented} prevented, net ${t.net>=0?"+":""}${t.net} tokens`:" Ledger: no turns recorded"),n(" To keep your lessons first, write them to disk:"),n(" npx @cachly-dev/mcp-server@latest export")}function X(t,e,n){n.ausgabe(""),n.ausgabe(t);for(const r of e)n.ausgabe(` ${et[r.aktion].padEnd(14)} ${V(r,n)} (${r.was})`)}function q(t,e,n){n.ausgabe(""),n.ausgabe("By hand (uninstall cannot do these):"),n.ausgabe(' - If you registered cachly with "codex mcp add" or "gemini mcp add -s user", it is in ~/.codex/config.toml or ~/.gemini/settings.json. Remove the entry named cachly there (the project files above are handled).'),n.ausgabe(' - Uninstall the JetBrains plugin "Cachly Brain" (Settings, Plugins) and the VS Code extension "cachly Brain" (cachly-dev.cachly-brain), if you installed them.');for(const r of t.vonHand)(r.stufe==="projekt"||e)&&n.ausgabe(` - ${r.text}`)}function Q(t,e){e.ausgabe("");for(const r of t){if(r.fund.aktion==="melden")continue;const o=r.status==="entfernt"?"removed":"skipped";e.ausgabe(` ${o.padEnd(8)} ${V(r.fund,e)}${r.grund?` (${r.grund})`:""}`)}const n=t.filter(r=>r.fund.aktion!=="melden");e.ausgabe(`Done: ${n.filter(r=>r.status==="entfernt").length} removed, ${n.filter(r=>r.status==="uebersprungen").length} skipped.`)}function nt(t){return{dryRun:t.includes("--dry-run"),ja:t.includes("--yes")||t.includes("-y"),global:t.includes("--global")}}async function jt(t,e){const n=nt(t),r=Qe({projekt:e.projekt,heim:e.heim,tmp:e.tmp}),o=await Ze({heim:e.heim,schluessel:e.schluessel,instanz:e.instanz||r.instanz,apiUrl:e.apiUrl,fetchFn:e.fetchFn});tt(o,e);const i=r.funde.filter(d=>d.stufe==="projekt"),a=r.funde.filter(d=>d.stufe==="global"),c=i.filter(d=>d.aktion!=="melden"),s=a.filter(d=>d.aktion!=="melden");if(i.length===0&&(!n.global||a.length===0))return e.ausgabe(""),e.ausgabe(`Nothing found in ${e.projekt}${n.global?" or your home folder":""}: cachly has not written anything here that uninstall can remove.`),!n.global&&s.length>0&&e.ausgabe(`Your home folder still holds ${s.length} cachly files (key, ledger, caches). "uninstall --global" removes them.`),q(r,n.global,e),e.ausgabe(""),e.ausgabe(B),0;if(i.length>0&&X(`In this project (${e.projekt}):`,i,e),n.global&&a.length>0&&X("In your home folder and temp folder (--global):",a,e),q(r,n.global,e),e.ausgabe(""),e.ausgabe(B),n.dryRun)return e.ausgabe(""),e.ausgabe("Dry run: nothing was changed."),!n.global&&s.length>0&&e.ausgabe(`Your home and temp folders hold ${s.length} more cachly files (key, ledger, caches); add --global to include them.`),0;if(!(c.length>0||n.global&&s.length>0))return e.ausgabe(""),e.ausgabe("Nothing to remove."),0;if(!n.ja&&!e.istTty)return e.ausgabe(""),e.ausgabe('This is not a terminal and --yes is missing: nothing was changed. Run it in a terminal, or add --yes. "--dry-run" only shows the plan.'),1;let h=0,u=0;if(c.length>0)if(n.ja||await e.frage(`
|
|
15
|
+
Remove these ${c.length} items from this project? [y/N] `)){const m=Y(i);Q(m,e),h+=m.filter(f=>f.status==="entfernt").length,u+=m.filter(f=>f.status==="uebersprungen"&&f.fund.aktion!=="melden").length}else e.ausgabe("Project: nothing was changed.");if(n.global&&s.length>0)if(e.ausgabe(""),e.ausgabe("Home folder: this removes your key file. Other projects on this computer lose their access to the Brain."),o.schluessel==="test"&&e.ausgabe('It is a test key. Without it you cannot reach the test Brain again. "npx @cachly-dev/mcp-server@latest claim" keeps it in your own account first.'),n.ja||await e.frage(`
|
|
16
|
+
Remove these ${s.length} items from your home and temp folder? [y/N] `)){const m=Y(a);Q(m,e),h+=m.filter(f=>f.status==="entfernt").length,u+=m.filter(f=>f.status==="uebersprungen"&&f.fund.aktion!=="melden").length}else e.ausgabe("Home folder: nothing was changed.");else!n.global&&s.length>0&&(e.ausgabe(""),e.ausgabe(`Your home folder still holds ${s.length} cachly files (key, ledger, caches). "uninstall --global" removes them, with its own question.`));return h===0&&u===0&&e.ausgabe("Nothing was changed."),u>0?1:0}export{Re as KAPUTTER_STOP_HOOK,Me as entferneAnweisungsBlock,Ke as entferneGitHookBloecke,U as entferneHookEintraege,w as entferneMcpEintrag,Y as fuehreAus,De as istCachlyAblage,Le as istLeerNachRueckbau,_ as klassifiziereAmbientHook,ze as klassifiziereClaudeHook,Qe as plane,Ze as sammleBestand,jt as uninstallBefehl};
|
package/glama.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cachly-dev/mcp-server",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.208",
|
|
4
4
|
"mcpName": "io.github.cachly-dev/mcp-server",
|
|
5
5
|
"description": "Solve it once. From then on, your AI knows. Experience for coding agents, EU-hosted: an MCP server for Claude Code, Cursor, Copilot & Windsurf. Learns from every bug fix, commit and CI run.",
|
|
6
6
|
"type": "module",
|
package/server.json
CHANGED
|
@@ -6,13 +6,13 @@
|
|
|
6
6
|
"url": "https://github.com/cachly-dev/cachly-mcp",
|
|
7
7
|
"source": "github"
|
|
8
8
|
},
|
|
9
|
-
"version": "0.10.
|
|
9
|
+
"version": "0.10.208",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"name": "@cachly-dev/mcp-server",
|
|
14
14
|
"identifier": "@cachly-dev/mcp-server",
|
|
15
|
-
"version": "0.10.
|
|
15
|
+
"version": "0.10.208",
|
|
16
16
|
"transport": {
|
|
17
17
|
"type": "stdio"
|
|
18
18
|
}
|