@cachly-dev/mcp-server 0.10.204 → 0.10.205

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.
@@ -1,9 +1,9 @@
1
- import{existsSync as A,readFileSync as D}from"node:fs";import{readFile as H,writeFile as k,chmod as R,mkdir as E}from"node:fs/promises";import{dirname as L,resolve as l}from"node:path";import{fileURLToPath as et}from"node:url";import{CURSOR_FLAG as rt}from"./cursor-hook.js";import{COPILOT_FLAG as nt,COPILOT_HOOK_EVENTS as st}from"./copilot-hook.js";import{CODEX_FLAG as it,CODEX_HOOK_EVENTS as ct}from"./codex-hook.js";import{GEMINI_FLAG as at,GEMINI_HOOK_EVENTS as ut}from"./gemini-hook.js";import{istCachlyEintrag as j}from"./hook-zugang.js";const G="v5",Zt="ambient-recall",S="cachly-ambient-einblendung.mjs";function y(t){return t.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}function P(t,o){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${G}`,"// Pushes relevant memory into context automatically. Cross-platform Node hook","// (no shell script \u2014 runs identically on Windows/macOS/Linux). Never blocks","// the agent: every failure path exits 0 with no output (graceful degrade).",`// Runs the hook bundle next to this file (${S}) in this process.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${y(o.instanceId)}';`,`process.env.CACHLY_HOOK_EVENT = '${y(t)}';`,`process.argv.splice(2, process.argv.length, '${y(t)}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
2
- `)}function M(){const t=L(et(import.meta.url));for(const o of[l(t,"..",w,S),l(t,"..","..",w,S)])if(A(o))return o;return null}function mt(t){return P("SessionStart",t)}function pt(t){return P("UserPromptSubmit",t)}function lt(t){return P("PreToolUse",t)}function St(t){return P("Stop",t)}const ft={SessionStart:30,UserPromptSubmit:10,PreToolUse:10,Stop:60},ht="Edit|Write|MultiEdit|NotebookEdit";function v(t,o){const e=(r,s,u)=>({...u?{matcher:u}:{},hooks:[{type:"command",command:`node "${s}"${o?` ${o(r)}`:""}`,timeout:ft[r]}]}),n={SessionStart:[e("SessionStart",t.sessionStart)],UserPromptSubmit:[e("UserPromptSubmit",t.userPromptSubmit)]};return t.preToolUse&&(n.PreToolUse=[e("PreToolUse",t.preToolUse,ht)]),t.stop&&(n.Stop=[e("Stop",t.stop)]),n}const K=".claude/hooks",dt=".claude/settings.json",J={SessionStart:"cachly-ambient-session-start.mjs",UserPromptSubmit:"cachly-ambient-prompt-submit.mjs",PreToolUse:"cachly-ambient-pre-tool.mjs",Stop:"cachly-ambient-stop.mjs"},bt=".claude/hooks/cachly-ambient-";function kt(t,o){const e=t.hooks??[];return e.length>0&&e.every(n=>{const r=n.command??"";return r.includes(bt)||o.has(r)||[...o].some(s=>r.includes(`"${s}"`))})}function gt(t,o){const e={...t,hooks:{...t.hooks??{}}},n=e.hooks,r=v(o),s=new Set([o.sessionStart,o.userPromptSubmit,o.preToolUse,o.stop].filter(c=>!!c));for(const[c,i]of Object.entries(r)){const a=(Array.isArray(n[c])?n[c]:[]).filter(f=>!kt(f,s));n[c]=[...a,...i]}const u=JSON.stringify(e)!==JSON.stringify(t);return{settings:e,changed:u}}async function qt(t,o,e,n={}){const r=l(t,K);await E(r,{recursive:!0});const s={instanceId:o,apiKey:e},u=["SessionStart","UserPromptSubmit","PreToolUse","Stop"],c={SessionStart:mt(s),UserPromptSubmit:pt(s),PreToolUse:lt(s),Stop:St(s)},i=m=>l(r,J[m]),a=M();if(!a)throw new Error(`cachly hook bundle ${S} missing from the package`);const f=D(a,"utf-8"),b=l(r,S),g=async m=>{try{return await H(m,"utf-8")}catch{return""}};let U=!1,O=await g(b)===f;for(const m of u){const $=await g(i(m));$&&(U=!0),$!==c[m]+`
3
- `&&(O=!1)}const d=O?"unchanged":U?"upgraded":"written";if(d!=="unchanged"){await k(b,f,"utf-8");for(const m of u)await k(i(m),c[m]+`
4
- `,"utf-8"),await R(i(m),493).catch(()=>{})}const p=l(t,dt),h=A(p);let N={};if(h)try{N=JSON.parse(await H(p,"utf-8"))}catch{N={}}const T=m=>n.portable?`$CLAUDE_PROJECT_DIR/${K}/${J[m]}`:i(m),{settings:tt,changed:ot}=gt(N,{sessionStart:T("SessionStart"),userPromptSubmit:T("UserPromptSubmit"),preToolUse:T("PreToolUse"),stop:T("Stop")});let _;return h?ot?_="merged":_="unchanged":_="written",_!=="unchanged"&&(await E(l(t,".claude"),{recursive:!0}),await k(p,JSON.stringify(tt,null,2)+`
5
- `,"utf-8")),{sessionStartPath:i("SessionStart"),promptSubmitPath:i("UserPromptSubmit"),preToolUsePath:i("PreToolUse"),stopPath:i("Stop"),bundlePath:b,scripts:d,settings:_}}const B=".cursor/hooks",Ot=".cursor/hooks.json",F="cachly-ambient-cursor.mjs",_t={sessionStart:30,beforeSubmitPrompt:10,postToolUse:5};function I(t,o,e,n){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${G}`,`// Einblendung fuer ${t}: ${e.join(", ")}.`,"// Blockiert nie: jeder Fehler endet mit Exit 0. Ruft das Buendel daneben",`// (${S}) in diesem Prozess.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${y(n.instanceId)}';`,`process.argv.push('${o}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
6
- `)}function Tt(t){return I("Cursor",rt,["sessionStart","beforeSubmitPrompt","postToolUse"],t)}function Et(){const t=o=>[{command:`node ${B}/${F} ${o}`,timeout:_t[o]}];return{sessionStart:t("sessionStart"),beforeSubmitPrompt:t("beforeSubmitPrompt"),postToolUse:t("postToolUse")}}function yt(t){return V(t,Et())}function V(t,o){const e={...t.hooks??{}};for(const[r,s]of Object.entries(o)){Y(e[r],r);const u=(e[r]??[]).filter(c=>!j(c));e[r]=[...u,...s]}const n={...t,version:typeof t.version=="number"?t.version:1,hooks:e};return{datei:n,changed:JSON.stringify(n)!==JSON.stringify(t)}}function X(t,o){const e={...t.hooks??{}};for(const[r,s]of Object.entries(o)){Y(e[r],r);const u=(e[r]??[]).flatMap(c=>{const i=c?.hooks;if(!Array.isArray(i))return[c];const a=i.filter(f=>!j(f));return a.length===i.length?[c]:a.length?[{...c,hooks:a}]:[]});e[r]=[...u,...s]}const n={...t,hooks:e};return{datei:n,changed:JSON.stringify(n)!==JSON.stringify(t)}}async function x(t){const o=l(t.projectDir,t.hookDir),e=M();if(!e)throw new Error(`cachly hook bundle ${S} missing from the package`);const n=D(e,"utf-8"),r=l(o,S),s=l(o,t.skriptName),u=t.skript+`
7
- `,c=async p=>{try{return await H(p,"utf-8")}catch{return""}},i=l(t.projectDir,t.configDatei),a=A(i)?await c(i):"",f=!a.trim();let b;try{const p=a.charCodeAt(0)===65279?a.slice(1):a,h=f?{}:JSON.parse(p);if(!z(h))throw new C("is not a JSON object");if(h.hooks!==void 0&&!z(h.hooks))throw new C('has a "hooks" field that is not an object');b=t.merge(h,s)}catch(p){const h=p instanceof C?p.message:/^\s*\/\/|\/\*/m.test(a)?"has comments, and cachly only rewrites plain JSON":"is not valid JSON";return{scriptPath:s,bundlePath:r,hooksPath:i,scripts:"unchanged",hooks:"skipped",grund:h}}await E(o,{recursive:!0});const g=await c(s),O=g===u&&await c(r)===n?"unchanged":g?"upgraded":"written";O!=="unchanged"&&(await k(r,n,"utf-8"),await k(s,u,"utf-8"),await R(s,493).catch(()=>{}));let d;if(f?d="written":b.changed?d="merged":d="unchanged",d!=="unchanged"){const p=/^([ \t]+)"/m.exec(a)?.[1]??2;await E(L(i),{recursive:!0}),await k(i,JSON.stringify(b.datei,null,p)+`
8
- `,"utf-8")}return{scriptPath:s,bundlePath:r,hooksPath:i,scripts:O,hooks:d}}function z(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}class C extends Error{}function Y(t,o){if(t!==void 0&&!Array.isArray(t))throw new C(`has a "hooks.${o}" entry that is not a list`)}async function to(t,o){return x({projectDir:t,hookDir:B,skriptName:F,skript:Tt({instanceId:o}),configDatei:Ot,merge:e=>yt(e)})}const W=".github/hooks",Pt=".github/hooks/cachly-ambient.json",Q="cachly-ambient-copilot.mjs",It={sessionStart:30,userPromptSubmitted:10,postToolUse:5};function xt(t){return I("VS Code / Copilot",nt,st,t)}function Ct(){const t=o=>[{type:"command",command:`node ${W}/${Q} ${o}`,cwd:".",timeoutSec:It[o]}];return{sessionStart:t("sessionStart"),userPromptSubmitted:t("userPromptSubmitted"),postToolUse:t("postToolUse")}}function Ut(t){return V(t,Ct())}async function oo(t,o){return x({projectDir:t,hookDir:W,skriptName:Q,skript:xt({instanceId:o}),configDatei:Pt,merge:e=>Ut(e)})}const Nt=".codex/hooks",At=".codex/hooks.json",Ht="cachly-ambient-codex.mjs",wt={SessionStart:30,UserPromptSubmit:10};function $t(t){return I("Codex",it,ct,t)}function Dt(t){const o=e=>[{hooks:[{type:"command",command:`node "${t}" ${e}`,timeout:wt[e]}]}];return{SessionStart:o("SessionStart"),UserPromptSubmit:o("UserPromptSubmit")}}function Rt(t,o){return X(t,Dt(o))}async function eo(t,o){return x({projectDir:t,hookDir:Nt,skriptName:Ht,skript:$t({instanceId:o}),configDatei:At,merge:(e,n)=>Rt(e,n)})}const Z=".gemini/hooks",Lt=".gemini/settings.json",q="cachly-ambient-gemini.mjs",jt={SessionStart:3e4,BeforeAgent:1e4},Gt={SessionStart:"cachly-briefing",BeforeAgent:"cachly-recall"};function Mt(t){return I("Gemini CLI",at,ut,t)}function vt(){const t=o=>[{hooks:[{name:Gt[o],type:"command",command:`node ${Z}/${q} ${o}`,timeout:jt[o]}]}];return{SessionStart:t("SessionStart"),BeforeAgent:t("BeforeAgent")}}function Kt(t){return X(t,vt())}async function ro(t,o){return x({projectDir:t,hookDir:Z,skriptName:q,skript:Mt({instanceId:o}),configDatei:Lt,merge:e=>Kt(e)})}const no=["SessionStart","UserPromptSubmit","Stop"],w="hooks";function so(){const t=`\${CLAUDE_PLUGIN_ROOT}/${w}/${S}`,o=v({sessionStart:t,userPromptSubmit:t,stop:t},e=>`${e} --plugin`);return JSON.stringify({hooks:o},null,2)+`
9
- `}export{Zt as AMBIENT_CLI_SUBCOMMAND,G as AMBIENT_HOOK_VERSION,K as CLAUDE_HOOK_DIR,dt as CLAUDE_SETTINGS_DATEI,At as CODEX_HOOKS_DATEI,Nt as CODEX_HOOK_DIR,Ht as CODEX_SKRIPT,wt as CODEX_TIMEOUTS,Pt as COPILOT_HOOKS_DATEI,W as COPILOT_HOOK_DIR,Q as COPILOT_SKRIPT,It as COPILOT_TIMEOUTS,Ot as CURSOR_HOOKS_DATEI,B as CURSOR_HOOK_DIR,F as CURSOR_SKRIPT,_t as CURSOR_TIMEOUTS,Z as GEMINI_HOOK_DIR,Lt as GEMINI_SETTINGS_DATEI,q as GEMINI_SKRIPT,jt as GEMINI_TIMEOUTS_MS,S as HOOK_BUENDEL,w as PLUGIN_HOOK_DIR,no as PLUGIN_HOOK_EVENTS,ht as PRE_TOOL_USE_MATCHER,v as buildAmbientSettingsHooks,$t as buildCodexHook,Dt as buildCodexHooks,xt as buildCopilotHook,Ct as buildCopilotHooks,Tt as buildCursorHook,Et as buildCursorHooks,Mt as buildGeminiHook,vt as buildGeminiHooks,so as buildPluginHooksJson,lt as buildPreToolUseHook,mt as buildSessionStartHook,St as buildStopHook,pt as buildUserPromptSubmitHook,M as hookBuendelQuelle,qt as installAmbientHooks,eo as installCodexHooks,oo as installCopilotHooks,to as installCursorHooks,ro as installGeminiHooks,gt as mergeAmbientSettings,Rt as mergeCodexHooks,Ut as mergeCopilotHooks,yt as mergeCursorHooks,Kt as mergeGeminiHooks};
1
+ import{existsSync as H,readFileSync as R}from"node:fs";import{readFile as j,writeFile as T,chmod as L,mkdir as x}from"node:fs/promises";import{dirname as G,resolve as l}from"node:path";import{fileURLToPath as rt}from"node:url";import{CURSOR_FLAG as nt}from"./cursor-hook.js";import{COPILOT_FLAG as st,COPILOT_HOOK_EVENTS as it}from"./copilot-hook.js";import{CODEX_FLAG as ct,CODEX_HOOK_EVENTS as at}from"./codex-hook.js";import{GEMINI_FLAG as ut,GEMINI_HOOK_EVENTS as mt}from"./gemini-hook.js";import{istCachlyEintrag as M}from"./hook-zugang.js";const v="v5",qt="ambient-recall",S="cachly-ambient-einblendung.mjs";function U(t){return t.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}function C(t,o){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${v}`,"// Pushes relevant memory into context automatically. Cross-platform Node hook","// (no shell script \u2014 runs identically on Windows/macOS/Linux). Never blocks","// the agent: every failure path exits 0 with no output (graceful degrade).",`// Runs the hook bundle next to this file (${S}) in this process.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${U(o.instanceId)}';`,`process.env.CACHLY_HOOK_EVENT = '${U(t)}';`,`process.argv.splice(2, process.argv.length, '${U(t)}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
2
+ `)}function K(){const t=G(rt(import.meta.url));for(const o of[l(t,"..",$,S),l(t,"..","..",$,S)])if(H(o))return o;return null}function pt(t){return C("SessionStart",t)}function lt(t){return C("UserPromptSubmit",t)}function St(t){return C("PreToolUse",t)}function ft(t){return C("Stop",t)}const ht={SessionStart:30,UserPromptSubmit:10,PreToolUse:10,Stop:60},dt="Edit|Write|MultiEdit|NotebookEdit";function J(t,o){const e=(r,i,m)=>({...m?{matcher:m}:{},hooks:[{type:"command",command:`node "${i}"${o?` ${o(r)}`:""}`,timeout:ht[r]}]}),s={SessionStart:[e("SessionStart",t.sessionStart)],UserPromptSubmit:[e("UserPromptSubmit",t.userPromptSubmit)]};return t.preToolUse&&(s.PreToolUse=[e("PreToolUse",t.preToolUse,dt)]),t.stop&&(s.Stop=[e("Stop",t.stop)]),s}const B=".claude/hooks",bt=".claude/settings.json",F={SessionStart:"cachly-ambient-session-start.mjs",UserPromptSubmit:"cachly-ambient-prompt-submit.mjs",PreToolUse:"cachly-ambient-pre-tool.mjs",Stop:"cachly-ambient-stop.mjs"},gt=".claude/hooks/cachly-ambient-";function kt(t,o){const e=t.hooks??[];return e.length>0&&e.every(s=>{const r=s.command??"";return r.replace(/\\/g,"/").includes(gt)||o.has(r)||[...o].some(i=>r.includes(`"${i}"`))})}function Ot(t,o){const e={...t,hooks:{...t.hooks??{}}},s=e.hooks,r=J(o),i=new Set([o.sessionStart,o.userPromptSubmit,o.preToolUse,o.stop].filter(c=>!!c));for(const[c,n]of Object.entries(r)){const u=(Array.isArray(s[c])?s[c]:[]).filter(f=>!kt(f,i));s[c]=[...u,...n]}const m=JSON.stringify(e)!==JSON.stringify(t);return{settings:e,changed:m}}async function to(t,o,e,s={}){const r=l(t,B),i={instanceId:o,apiKey:e},m=["SessionStart","UserPromptSubmit","PreToolUse","Stop"],c={SessionStart:pt(i),UserPromptSubmit:lt(i),PreToolUse:St(i),Stop:ft(i)},n=a=>l(r,F[a]),u=K();if(!u)throw new Error(`cachly hook bundle ${S} missing from the package`);const f=R(u,"utf-8"),d=l(r,S),O=async a=>{try{return await j(a,"utf-8")}catch{return""}},E=l(t,bt),_=H(E);let b={};if(_){const a=await O(E);try{const g=a.charCodeAt(0)===65279?a.slice(1):a,P=g.trim()?JSON.parse(g):{};if(!w(P))throw new k("is not a JSON object");if(P.hooks!==void 0&&!w(P.hooks))throw new k('has a "hooks" field that is not an object');b=P}catch(g){const P=g instanceof k?g.message:/^\s*\/\/|\/\*/m.test(a)?"has comments, and cachly only rewrites plain JSON":"is not valid JSON";return{sessionStartPath:n("SessionStart"),promptSubmitPath:n("UserPromptSubmit"),preToolUsePath:n("PreToolUse"),stopPath:n("Stop"),bundlePath:d,scripts:"unchanged",settings:"skipped",grund:P}}}let p=!1,h=await O(d)===f;for(const a of m){const g=await O(n(a));g&&(p=!0),g!==c[a]+`
3
+ `&&(h=!1)}const D=h?"unchanged":p?"upgraded":"written";if(D!=="unchanged"){await x(r,{recursive:!0}),await T(d,f,"utf-8");for(const a of m)await T(n(a),c[a]+`
4
+ `,"utf-8"),await L(n(a),493).catch(()=>{})}const I=a=>s.portable?`$CLAUDE_PROJECT_DIR/${B}/${F[a]}`:n(a),{settings:ot,changed:et}=Ot(b,{sessionStart:I("SessionStart"),userPromptSubmit:I("UserPromptSubmit"),preToolUse:I("PreToolUse"),stop:I("Stop")});let y;return _?et?y="merged":y="unchanged":y="written",y!=="unchanged"&&(await x(l(t,".claude"),{recursive:!0}),await T(E,JSON.stringify(ot,null,2)+`
5
+ `,"utf-8")),{sessionStartPath:n("SessionStart"),promptSubmitPath:n("UserPromptSubmit"),preToolUsePath:n("PreToolUse"),stopPath:n("Stop"),bundlePath:d,scripts:D,settings:y}}const V=".cursor/hooks",Pt=".cursor/hooks.json",X="cachly-ambient-cursor.mjs",Tt={sessionStart:30,beforeSubmitPrompt:10,postToolUse:5};function N(t,o,e,s){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${v}`,`// Einblendung fuer ${t}: ${e.join(", ")}.`,"// Blockiert nie: jeder Fehler endet mit Exit 0. Ruft das Buendel daneben",`// (${S}) in diesem Prozess.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${U(s.instanceId)}';`,`process.argv.push('${o}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
6
+ `)}function _t(t){return N("Cursor",nt,["sessionStart","beforeSubmitPrompt","postToolUse"],t)}function yt(){const t=o=>[{command:`node ${V}/${X} ${o}`,timeout:Tt[o]}];return{sessionStart:t("sessionStart"),beforeSubmitPrompt:t("beforeSubmitPrompt"),postToolUse:t("postToolUse")}}function Et(t){return z(t,yt())}function z(t,o){const e={...t.hooks??{}};for(const[r,i]of Object.entries(o)){W(e[r],r);const m=(e[r]??[]).filter(c=>!M(c));e[r]=[...m,...i]}const s={...t,version:typeof t.version=="number"?t.version:1,hooks:e};return{datei:s,changed:JSON.stringify(s)!==JSON.stringify(t)}}function Y(t,o){const e={...t.hooks??{}};for(const[r,i]of Object.entries(o)){W(e[r],r);const m=(e[r]??[]).flatMap(c=>{const n=c?.hooks;if(!Array.isArray(n))return[c];const u=n.filter(f=>!M(f));return u.length===n.length?[c]:u.length?[{...c,hooks:u}]:[]});e[r]=[...m,...i]}const s={...t,hooks:e};return{datei:s,changed:JSON.stringify(s)!==JSON.stringify(t)}}async function A(t){const o=l(t.projectDir,t.hookDir),e=K();if(!e)throw new Error(`cachly hook bundle ${S} missing from the package`);const s=R(e,"utf-8"),r=l(o,S),i=l(o,t.skriptName),m=t.skript+`
7
+ `,c=async p=>{try{return await j(p,"utf-8")}catch{return""}},n=l(t.projectDir,t.configDatei),u=H(n)?await c(n):"",f=!u.trim();let d;try{const p=u.charCodeAt(0)===65279?u.slice(1):u,h=f?{}:JSON.parse(p);if(!w(h))throw new k("is not a JSON object");if(h.hooks!==void 0&&!w(h.hooks))throw new k('has a "hooks" field that is not an object');d=t.merge(h,i)}catch(p){const h=p instanceof k?p.message:/^\s*\/\/|\/\*/m.test(u)?"has comments, and cachly only rewrites plain JSON":"is not valid JSON";return{scriptPath:i,bundlePath:r,hooksPath:n,scripts:"unchanged",hooks:"skipped",grund:h}}await x(o,{recursive:!0});const O=await c(i),_=O===m&&await c(r)===s?"unchanged":O?"upgraded":"written";_!=="unchanged"&&(await T(r,s,"utf-8"),await T(i,m,"utf-8"),await L(i,493).catch(()=>{}));let b;if(f?b="written":d.changed?b="merged":b="unchanged",b!=="unchanged"){const p=/^([ \t]+)"/m.exec(u)?.[1]??2;await x(G(n),{recursive:!0}),await T(n,JSON.stringify(d.datei,null,p)+`
8
+ `,"utf-8")}return{scriptPath:i,bundlePath:r,hooksPath:n,scripts:_,hooks:b}}function w(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}class k extends Error{}function W(t,o){if(t!==void 0&&!Array.isArray(t))throw new k(`has a "hooks.${o}" entry that is not a list`)}async function oo(t,o){return A({projectDir:t,hookDir:V,skriptName:X,skript:_t({instanceId:o}),configDatei:Pt,merge:e=>Et(e)})}const Q=".github/hooks",It=".github/hooks/cachly-ambient.json",Z="cachly-ambient-copilot.mjs",xt={sessionStart:30,userPromptSubmitted:10,postToolUse:5};function Ut(t){return N("VS Code / Copilot",st,it,t)}function Ct(){const t=o=>[{type:"command",command:`node ${Q}/${Z} ${o}`,cwd:".",timeoutSec:xt[o]}];return{sessionStart:t("sessionStart"),userPromptSubmitted:t("userPromptSubmitted"),postToolUse:t("postToolUse")}}function Nt(t){return z(t,Ct())}async function eo(t,o){return A({projectDir:t,hookDir:Q,skriptName:Z,skript:Ut({instanceId:o}),configDatei:It,merge:e=>Nt(e)})}const At=".codex/hooks",wt=".codex/hooks.json",Ht="cachly-ambient-codex.mjs",$t={SessionStart:30,UserPromptSubmit:10};function Dt(t){return N("Codex",ct,at,t)}function Rt(t){const o=e=>[{hooks:[{type:"command",command:`node "${t}" ${e}`,timeout:$t[e]}]}];return{SessionStart:o("SessionStart"),UserPromptSubmit:o("UserPromptSubmit")}}function jt(t,o){return Y(t,Rt(o))}async function ro(t,o){return A({projectDir:t,hookDir:At,skriptName:Ht,skript:Dt({instanceId:o}),configDatei:wt,merge:(e,s)=>jt(e,s)})}const q=".gemini/hooks",Lt=".gemini/settings.json",tt="cachly-ambient-gemini.mjs",Gt={SessionStart:3e4,BeforeAgent:1e4},Mt={SessionStart:"cachly-briefing",BeforeAgent:"cachly-recall"};function vt(t){return N("Gemini CLI",ut,mt,t)}function Kt(){const t=o=>[{hooks:[{name:Mt[o],type:"command",command:`node ${q}/${tt} ${o}`,timeout:Gt[o]}]}];return{SessionStart:t("SessionStart"),BeforeAgent:t("BeforeAgent")}}function Jt(t){return Y(t,Kt())}async function no(t,o){return A({projectDir:t,hookDir:q,skriptName:tt,skript:vt({instanceId:o}),configDatei:Lt,merge:e=>Jt(e)})}const so=["SessionStart","UserPromptSubmit","Stop"],$="hooks";function io(){const t=`\${CLAUDE_PLUGIN_ROOT}/${$}/${S}`,o=J({sessionStart:t,userPromptSubmit:t,stop:t},e=>`${e} --plugin`);return JSON.stringify({hooks:o},null,2)+`
9
+ `}export{qt as AMBIENT_CLI_SUBCOMMAND,v as AMBIENT_HOOK_VERSION,B as CLAUDE_HOOK_DIR,bt as CLAUDE_SETTINGS_DATEI,wt as CODEX_HOOKS_DATEI,At as CODEX_HOOK_DIR,Ht as CODEX_SKRIPT,$t as CODEX_TIMEOUTS,It as COPILOT_HOOKS_DATEI,Q as COPILOT_HOOK_DIR,Z as COPILOT_SKRIPT,xt as COPILOT_TIMEOUTS,Pt as CURSOR_HOOKS_DATEI,V as CURSOR_HOOK_DIR,X as CURSOR_SKRIPT,Tt as CURSOR_TIMEOUTS,q as GEMINI_HOOK_DIR,Lt as GEMINI_SETTINGS_DATEI,tt as GEMINI_SKRIPT,Gt as GEMINI_TIMEOUTS_MS,S as HOOK_BUENDEL,$ as PLUGIN_HOOK_DIR,so as PLUGIN_HOOK_EVENTS,dt as PRE_TOOL_USE_MATCHER,J as buildAmbientSettingsHooks,Dt as buildCodexHook,Rt as buildCodexHooks,Ut as buildCopilotHook,Ct as buildCopilotHooks,_t as buildCursorHook,yt as buildCursorHooks,vt as buildGeminiHook,Kt as buildGeminiHooks,io as buildPluginHooksJson,St as buildPreToolUseHook,pt as buildSessionStartHook,ft as buildStopHook,lt as buildUserPromptSubmitHook,K as hookBuendelQuelle,to as installAmbientHooks,ro as installCodexHooks,eo as installCopilotHooks,oo as installCursorHooks,no as installGeminiHooks,Ot as mergeAmbientSettings,jt as mergeCodexHooks,Nt as mergeCopilotHooks,Et as mergeCursorHooks,Jt as mergeGeminiHooks};
package/dist/src/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import{setzeClientKennung as Pt}from"./herkunft.js";import{jwtExpiryMs as Nt,checkJwt as Ht,handleApiError as Mt,diagnoseAuth as Se,planAuthHeal as De,readClientCredentialsFromEnv as Dt,buildClientCredentialsBody as Ut,clientCredentialsTokenUrl as Jt}from"./auth.js";import{cachlyUrl as j}from"./cachly-url.js";import{nutzungsSchluessel as zt}from"./werkzeug-nutzung.js";import{istLieferung as Ft,lieferSchluessel as Wt,tokenDerAntwort as Yt,hatTreffer as Kt,trefferSchluessel as Ue}from"./geliefert.js";import{notify as Je}from"./notifier.js";import{fileURLToPath as ze}from"node:url";import{createRequire as qt}from"node:module";import{execFile as Ae}from"node:child_process";const Gt=process.argv[1]!=null&&(process.argv[1]===ze(import.meta.url)||process.argv[1].endsWith("/dist/index.js")||process.argv[1].endsWith("/src/index.ts"));import{Server as Fe}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Vt}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as Zt}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as We,ErrorCode as ie,ListPromptsRequestSchema as Ye,ListResourceTemplatesRequestSchema as Ke,ListResourcesRequestSchema as qe,ListToolsRequestSchema as Ge,McpError as te}from"@modelcontextprotocol/sdk/types.js";import{Redis as Ve}from"ioredis";let x=process.env.CACHLY_API_URL??"https://api.cachly.dev",y=Be()??"";le(y);const js=process.env.CACHLY_EMBED_MODEL??"",D=(()=>{try{const e=qt(import.meta.url);for(const t of["../../package.json","../package.json"])try{const s=e(t);if(s.name==="@cachly-dev/mcp-server"&&s.version)return s.version}catch{}}catch{}return"0.10.100"})(),Qt=Number(process.env.CACHLY_PROVISION_TIMEOUT_MS??9e4);let P=xe(process.env.CACHLY_BRAIN_INSTANCE_ID);function oe(){return y||Be()||""}function F(){return xe(process.env.CACHLY_BRAIN_INSTANCE_ID)||ut()||""}let Z=0,de=null,Ze=!1;async function Xt(){let e=[];try{V.getClientCapabilities()?.roots&&(e=(await V.listRoots(void 0,{timeout:3e3})).roots)}catch{}return Tn({wurzeln:e,env:process.env,cwd:process.cwd(),dateiPfad:ze})}function re(){return Ze?gt(process.env):!1}function Ce(e,t,s){!e||!re()||kn({instanzId:e,vomHook:s,verbindung:H,ausGit:n=>je("brain_from_git",n,H,N),projektOrdner:t?async()=>t:Xt,einbetten:n=>et(n,{geduld:"lang"}),hatEinbettung:mo,einbettenZweit:n=>et(n,{geduld:"lang",modell:go}),melde:n=>S("brain_from_git",{...y?{api_key:y}:{},instance_id:e,total:n,auto:"startwissen"}),startvorrat:n=>Pe("brain_seed_starter",n,H,N),meldeStartvorrat:n=>S("brain_seed_starter",{...y?{api_key:y}:{},instance_id:e,auto:!0},{seeded_count:n,auto:!0})})}function Te(){return re()&&En()}const eo=7e3,to=12e3,oo=18e4;let ve=null;function Ee(e){return ve||(ve=no(e).finally(()=>{ve=null})),ve}async function no(e){try{if(!y){const t=Date.now()+e;for(;!Le()&&vn({})&&Date.now()<t;)await new Promise(o=>setTimeout(o,hn));const s=Le();if(!s)return!1;y=s,le(s);const n=ut();n&&!P&&(P=n,Z=0),await ue(s),n&&await pe(n),S("instant_trial_started",{tool:"sessionstart-hook",...n?{instance_id:n}:{}})}if(re()&&mt()){const t=yn();t&&(Oe(t.instanzId,re(),Te()),Ce(t.instanzId,t.projekt||void 0,t.vomHook))}}catch{}return!!y}function so(){if(!gt(process.env))return;const e=Date.now()+oo,t=setInterval(()=>{if(Date.now()>e){clearInterval(t);return}y&&!mt()||Ee(0)},500);t.unref(),Ee(0)}async function io(){if(!y)return"";try{const e=await fetch(`${x}/api/v1/instances/auto`,{method:"POST",headers:{Authorization:`Bearer ${y}`,"Content-Type":"application/json"},signal:AbortSignal.timeout(12e3)});if(e.ok){const t=await e.json(),s=t.instance?.id??t.instance_id;if(s)return s}else fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({event:"auto_provision_failed",status:e.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}catch{fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"auto_provision_failed",status:0,reason:"network_error",version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}return""}async function Qe(){if(P)return P;if(!y)return"";if(de)return de;const e=Date.now();if(Z>0&&e-Z<3e4)return"";Z=e,de=(async()=>{try{const t=await fetch(`${x}/api/v1/instances`,{headers:{Authorization:`Bearer ${y}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(t.ok){const n=(await t.json())?.data??[],o=n.find(r=>r.status==="running")??n.find(r=>r.status==="provisioning");if(o)return P=o.id,Z=0,P;const c=await io();if(c)return P=c,Z=0,Oe(c,re(),Te()),pe(c),Ce(c),P}}catch{}return""})();try{return await de}finally{de=null}}let Ie=0;const ro=6e4;let ae="";async function ue(e){try{const{writeFile:t,mkdir:s,readFile:n}=await import("node:fs/promises"),{existsSync:o}=await import("node:fs"),{resolve:c,dirname:r}=await import("node:path"),a=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!a)return;const u=c(a,".claude","mcp.json");let m={};if(o(u))try{m=JSON.parse(await n(u,"utf-8"))}catch{}m.mcpServers??={};const l=m.mcpServers.cachly;if(l)l.env??={},l.env.CACHLY_JWT=e;else{const w={};w.CACHLY_JWT=e,m.mcpServers.cachly={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:w}}await s(r(u),{recursive:!0}),await t(u,JSON.stringify(m,null,2),"utf-8");const g=[c(a,".cursor","mcp.json"),c(a,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(g.map(async w=>{if(o(w))try{const v=await n(w,"utf-8"),b=JSON.parse(v),p=b?.mcpServers?.cachly;p?.env&&(p.env.CACHLY_JWT=e,await t(w,JSON.stringify(b,null,2),"utf-8"))}catch{}}))}catch{}}async function pe(e){if(e){dt(e,{apiKey:y});try{const{writeFile:t,readFile:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o}=await import("node:path"),c=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!c)return;const r=[o(c,".claude","mcp.json"),o(c,".cursor","mcp.json"),o(c,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(r.map(async a=>{if(n(a))try{const u=JSON.parse(await s(a,"utf-8")),m=u?.mcpServers?.cachly;m?.env&&(m.env.CACHLY_BRAIN_INSTANCE_ID=e,await t(a,JSON.stringify(u,null,2),"utf-8"))}catch{}}))}catch{}}}async function ao(){try{const e=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({name:"cachly-mcp-selfheal",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(!e.ok)return!1;const t=await e.json();return t.key?(y=t.key,le(t.key),ue(t.key),S("auth_self_healed",{reason:"near_expiry_refresh"}),!0):!1}catch{return!1}}async function Re(){const e=Se(y),t=De(e);if(t==="none")return ae="",!0;if(t==="refresh"){const s=Date.now();return s-Ie>=ro&&(Ie=s,await ao())?(ae="",!0):(ae=e.message,e.usable)}return ae=e.message,!1}function ce(e,t){const s=(r,a)=>{try{t?.(r,a)}catch{}},n=r=>{r?s(!1,r.code??r.message):s(!0)},o=zo(e);if(!o){s(!1,"keine-http-adresse");return}const c=Fo(o);try{process.platform==="win32"?Ae("cmd",["/c","start","",c],{windowsHide:!0},n):process.platform==="darwin"?Ae("open",[o],n):Ae("xdg-open",[o],n)}catch(r){s(!1,r instanceof Error?r.message:"unknown")}}let G=null;async function co(){try{const e=await fetch(`${x}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(8e3)});if(e.ok){const t=await e.json(),s=t.verification_uri||j("/device","ambient-signin"),n=`${s}${s.includes("?")?"&":"?"}code=${encodeURIComponent(t.user_code)}`;return{deviceCode:t.device_code,userCode:t.user_code,verifyUrl:n,pollInterval:(t.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}}catch{}try{const t=await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/auth/device",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id=cachly-cli&scope=openid",signal:AbortSignal.timeout(8e3)});if(!t.ok)return null;const s=await t.json();return{deviceCode:s.device_code,userCode:s.user_code,verifyUrl:s.verification_uri_complete,pollInterval:(s.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}catch{return null}}async function lo(e){if(Date.now()>e.deadline)return"expired";const t=async()=>{const n=await fetch(`${x}/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e.deviceCode}),signal:AbortSignal.timeout(8e3)});return n.ok?n.json():null},s=async()=>(await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`client_id=cachly-cli&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=${e.deviceCode}`,signal:AbortSignal.timeout(8e3)})).json();try{let n=await t().catch(()=>null);if(n||(n=await s().catch(()=>null)),!n)return"pending";if(n.access_token){let o=n.access_token;try{const c=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({name:"cachly-mcp-smithery",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(c.ok){const r=await c.json();r.key&&(o=r.key)}}catch{}return y=o,le(o),G=null,S("device_flow_completed"),ue(o),Q(o),Z=0,await Qe(),P&&pe(P),"done"}return n.error==="slow_down"&&(e.pollInterval=Math.min(e.pollInterval+2e3,15e3)),"pending"}catch{return"pending"}}async function Xe(e){if(e.polling)return"pending";e.polling=!0;try{return await lo(e)}finally{e.polling=!1}}function uo(e,t=Xe,s=o=>G===o,n=po){const o=async()=>{if(!s(e))return;let c="pending";try{c=await t(e)}catch{}if(c!=="done"){if(c==="expired"){s(e)&&(G=null);return}s(e)&&n(o,e.pollInterval)}};n(o,e.pollInterval)}function po(e,t){const s=setTimeout(e,t);typeof s.unref=="function"&&s.unref()}import{setEmbedJwt as le,computeEmbedding as et,hasEmbedProvider as mo,EMBED_PROVIDER as tt}from"./embeddings.js";import{ZWEIT_MODELL as go}from"./rangfolge-stellschrauben.js";import{tokenize as fo,splitMultiQuery as ho,levenshtein as yo,recencyBoost as bo,extractTimestamp as vo,STOPWORDS as wo,katakanaToRomaji as xo,arabicLightStem as _o,expandCrossLingual as $o,CROSS_LINGUAL_MAP as ko,ZERO_RESULTS_LOG as So,zeroResultsTotal as Ao}from"./search.js";const ne=new Map;function Co(e){return e<=1?200:null}async function H(e){if(!e)throw new te(ie.InvalidRequest,`\u23F3 Your Brain instance is still being set up.
2
+ import{setzeClientKennung as Nt}from"./herkunft.js";import{jwtExpiryMs as Pt,checkJwt as Ht,handleApiError as Mt,diagnoseAuth as Se,planAuthHeal as De,readClientCredentialsFromEnv as Dt,buildClientCredentialsBody as Ut,clientCredentialsTokenUrl as Jt}from"./auth.js";import{cachlyUrl as j}from"./cachly-url.js";import{nutzungsSchluessel as zt}from"./werkzeug-nutzung.js";import{istLieferung as Ft,lieferSchluessel as Wt,tokenDerAntwort as Yt,hatTreffer as Kt,trefferSchluessel as Ue}from"./geliefert.js";import{notify as Je}from"./notifier.js";import{fileURLToPath as ze}from"node:url";import{createRequire as qt}from"node:module";import{execFile as Ae}from"node:child_process";const Gt=process.argv[1]!=null&&(process.argv[1]===ze(import.meta.url)||process.argv[1].endsWith("/dist/index.js")||process.argv[1].endsWith("/src/index.ts"));import{Server as Fe}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Vt}from"@modelcontextprotocol/sdk/server/stdio.js";import{StreamableHTTPServerTransport as Zt}from"@modelcontextprotocol/sdk/server/streamableHttp.js";import{CallToolRequestSchema as We,ErrorCode as ie,ListPromptsRequestSchema as Ye,ListResourceTemplatesRequestSchema as Ke,ListResourcesRequestSchema as qe,ListToolsRequestSchema as Ge,McpError as te}from"@modelcontextprotocol/sdk/types.js";import{Redis as Ve}from"ioredis";let x=process.env.CACHLY_API_URL??"https://api.cachly.dev",y=Be()??"";le(y);const js=process.env.CACHLY_EMBED_MODEL??"",D=(()=>{try{const e=qt(import.meta.url);for(const t of["../../package.json","../package.json"])try{const s=e(t);if(s.name==="@cachly-dev/mcp-server"&&s.version)return s.version}catch{}}catch{}return"0.10.100"})(),Qt=Number(process.env.CACHLY_PROVISION_TIMEOUT_MS??9e4);let N=xe(process.env.CACHLY_BRAIN_INSTANCE_ID);function oe(){return y||Be()||""}function F(){return xe(process.env.CACHLY_BRAIN_INSTANCE_ID)||ut()||""}let Z=0,de=null,Ze=!1;async function Xt(){let e=[];try{V.getClientCapabilities()?.roots&&(e=(await V.listRoots(void 0,{timeout:3e3})).roots)}catch{}return Tn({wurzeln:e,env:process.env,cwd:process.cwd(),dateiPfad:ze})}function re(){return Ze?gt(process.env):!1}function Ce(e,t,s){!e||!re()||kn({instanzId:e,vomHook:s,verbindung:H,ausGit:n=>je("brain_from_git",n,H,P),projektOrdner:t?async()=>t:Xt,einbetten:n=>et(n,{geduld:"lang"}),hatEinbettung:mo,einbettenZweit:n=>et(n,{geduld:"lang",modell:go}),melde:n=>S("brain_from_git",{...y?{api_key:y}:{},instance_id:e,total:n,auto:"startwissen"}),startvorrat:n=>Ne("brain_seed_starter",n,H,P),meldeStartvorrat:n=>S("brain_seed_starter",{...y?{api_key:y}:{},instance_id:e,auto:!0},{seeded_count:n,auto:!0})})}function Te(){return re()&&En()}const eo=7e3,to=12e3,oo=18e4;let ve=null;function Ee(e){return ve||(ve=no(e).finally(()=>{ve=null})),ve}async function no(e){try{if(!y){const t=Date.now()+e;for(;!Le()&&vn({})&&Date.now()<t;)await new Promise(o=>setTimeout(o,hn));const s=Le();if(!s)return!1;y=s,le(s);const n=ut();n&&!N&&(N=n,Z=0),await ue(s),n&&await pe(n),S("instant_trial_started",{tool:"sessionstart-hook",...n?{instance_id:n}:{}})}if(re()&&mt()){const t=yn();t&&(Oe(t.instanzId,re(),Te()),Ce(t.instanzId,t.projekt||void 0,t.vomHook))}}catch{}return!!y}function so(){if(!gt(process.env))return;const e=Date.now()+oo,t=setInterval(()=>{if(Date.now()>e){clearInterval(t);return}y&&!mt()||Ee(0)},500);t.unref(),Ee(0)}async function io(){if(!y)return"";try{const e=await fetch(`${x}/api/v1/instances/auto`,{method:"POST",headers:{Authorization:`Bearer ${y}`,"Content-Type":"application/json"},signal:AbortSignal.timeout(12e3)});if(e.ok){const t=await e.json(),s=t.instance?.id??t.instance_id;if(s)return s}else fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({event:"auto_provision_failed",status:e.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}catch{fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"auto_provision_failed",status:0,reason:"network_error",version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}return""}async function Qe(){if(N)return N;if(!y)return"";if(de)return de;const e=Date.now();if(Z>0&&e-Z<3e4)return"";Z=e,de=(async()=>{try{const t=await fetch(`${x}/api/v1/instances`,{headers:{Authorization:`Bearer ${y}`,Accept:"application/json"},signal:AbortSignal.timeout(5e3)});if(t.ok){const n=(await t.json())?.data??[],o=n.find(r=>r.status==="running")??n.find(r=>r.status==="provisioning");if(o)return N=o.id,Z=0,N;const c=await io();if(c)return N=c,Z=0,Oe(c,re(),Te()),pe(c),Ce(c),N}}catch{}return""})();try{return await de}finally{de=null}}let Ie=0;const ro=6e4;let ae="";async function ue(e){try{const{writeFile:t,mkdir:s,readFile:n}=await import("node:fs/promises"),{existsSync:o}=await import("node:fs"),{resolve:c,dirname:r}=await import("node:path"),a=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!a)return;const u=c(a,".claude","mcp.json");let m={};if(o(u))try{m=JSON.parse(await n(u,"utf-8"))}catch{}m.mcpServers??={};const l=m.mcpServers.cachly;if(l)l.env??={},l.env.CACHLY_JWT=e;else{const w={};w.CACHLY_JWT=e,m.mcpServers.cachly={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:w}}await s(r(u),{recursive:!0}),await t(u,JSON.stringify(m,null,2),"utf-8");const g=[c(a,".cursor","mcp.json"),c(a,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(g.map(async w=>{if(o(w))try{const v=await n(w,"utf-8"),b=JSON.parse(v),p=b?.mcpServers?.cachly;p?.env&&(p.env.CACHLY_JWT=e,await t(w,JSON.stringify(b,null,2),"utf-8"))}catch{}}))}catch{}}async function pe(e){if(e){dt(e,{apiKey:y});try{const{writeFile:t,readFile:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o}=await import("node:path"),c=process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??"";if(!c)return;const r=[o(c,".claude","mcp.json"),o(c,".cursor","mcp.json"),o(c,".codeium","windsurf","mcp_config.json")];await Promise.allSettled(r.map(async a=>{if(n(a))try{const u=JSON.parse(await s(a,"utf-8")),m=u?.mcpServers?.cachly;m?.env&&(m.env.CACHLY_BRAIN_INSTANCE_ID=e,await t(a,JSON.stringify(u,null,2),"utf-8"))}catch{}}))}catch{}}}async function ao(){try{const e=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`},body:JSON.stringify({name:"cachly-mcp-selfheal",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(!e.ok)return!1;const t=await e.json();return t.key?(y=t.key,le(t.key),ue(t.key),S("auth_self_healed",{reason:"near_expiry_refresh"}),!0):!1}catch{return!1}}async function Re(){const e=Se(y),t=De(e);if(t==="none")return ae="",!0;if(t==="refresh"){const s=Date.now();return s-Ie>=ro&&(Ie=s,await ao())?(ae="",!0):(ae=e.message,e.usable)}return ae=e.message,!1}function ce(e,t){const s=(r,a)=>{try{t?.(r,a)}catch{}},n=r=>{r?s(!1,r.code??r.message):s(!0)},o=zo(e);if(!o){s(!1,"keine-http-adresse");return}const c=Fo(o);try{process.platform==="win32"?Ae("cmd",["/c","start","",c],{windowsHide:!0},n):process.platform==="darwin"?Ae("open",[o],n):Ae("xdg-open",[o],n)}catch(r){s(!1,r instanceof Error?r.message:"unknown")}}let G=null;async function co(){try{const e=await fetch(`${x}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(8e3)});if(e.ok){const t=await e.json(),s=t.verification_uri||j("/device","ambient-signin"),n=`${s}${s.includes("?")?"&":"?"}code=${encodeURIComponent(t.user_code)}`;return{deviceCode:t.device_code,userCode:t.user_code,verifyUrl:n,pollInterval:(t.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}}catch{}try{const t=await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/auth/device",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:"client_id=cachly-cli&scope=openid",signal:AbortSignal.timeout(8e3)});if(!t.ok)return null;const s=await t.json();return{deviceCode:s.device_code,userCode:s.user_code,verifyUrl:s.verification_uri_complete,pollInterval:(s.interval??5)*1e3,deadline:Date.now()+600*1e3,polling:!1}}catch{return null}}async function lo(e){if(Date.now()>e.deadline)return"expired";const t=async()=>{const n=await fetch(`${x}/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e.deviceCode}),signal:AbortSignal.timeout(8e3)});return n.ok?n.json():null},s=async()=>(await fetch("https://auth.cachly.dev/realms/cachly/protocol/openid-connect/token",{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:`client_id=cachly-cli&grant_type=urn:ietf:params:oauth:grant-type:device_code&device_code=${e.deviceCode}`,signal:AbortSignal.timeout(8e3)})).json();try{let n=await t().catch(()=>null);if(n||(n=await s().catch(()=>null)),!n)return"pending";if(n.access_token){let o=n.access_token;try{const c=await fetch(`${x}/api/v1/api-keys`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({name:"cachly-mcp-smithery",scope:"read_write"}),signal:AbortSignal.timeout(8e3)});if(c.ok){const r=await c.json();r.key&&(o=r.key)}}catch{}return y=o,le(o),G=null,S("device_flow_completed"),ue(o),Q(o),Z=0,await Qe(),N&&pe(N),"done"}return n.error==="slow_down"&&(e.pollInterval=Math.min(e.pollInterval+2e3,15e3)),"pending"}catch{return"pending"}}async function Xe(e){if(e.polling)return"pending";e.polling=!0;try{return await lo(e)}finally{e.polling=!1}}function uo(e,t=Xe,s=o=>G===o,n=po){const o=async()=>{if(!s(e))return;let c="pending";try{c=await t(e)}catch{}if(c!=="done"){if(c==="expired"){s(e)&&(G=null);return}s(e)&&n(o,e.pollInterval)}};n(o,e.pollInterval)}function po(e,t){const s=setTimeout(e,t);typeof s.unref=="function"&&s.unref()}import{setEmbedJwt as le,computeEmbedding as et,hasEmbedProvider as mo,EMBED_PROVIDER as tt}from"./embeddings.js";import{ZWEIT_MODELL as go}from"./rangfolge-stellschrauben.js";import{tokenize as fo,splitMultiQuery as ho,levenshtein as yo,recencyBoost as bo,extractTimestamp as vo,STOPWORDS as wo,katakanaToRomaji as xo,arabicLightStem as _o,expandCrossLingual as $o,CROSS_LINGUAL_MAP as ko,ZERO_RESULTS_LOG as So,zeroResultsTotal as Ao}from"./search.js";const ne=new Map;function Co(e){return e<=1?200:null}async function H(e){if(!e)throw new te(ie.InvalidRequest,`\u23F3 Your Brain instance is still being set up.
3
3
 
4
4
  This usually resolves in a few seconds \u2014 just call the tool again and it will connect automatically.
5
5
 
6
6
  If it keeps happening:
7
7
  \u2022 Run \`list_instances\` to check your instances, or
8
8
  \u2022 Set CACHLY_BRAIN_INSTANCE_ID in your MCP config, or
9
- \u2022 Reach us at support@cachly.dev.`);const t=ne.get(e);return t||_n(To,e,()=>Eo(e))}const To=new Map;async function Eo(e){W("verbindung: Instanz abfragen");let t=await N(`/api/v1/instances/${e}`);if(W(`verbindung: Instanz ${t.status}`),t=await xn(t,()=>N(`/api/v1/instances/${e}`),{fristMs:Qt,melde:r=>W(`verbindung: Instanz ${r.status}`)}),t.status!=="running"){fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"instance_not_reachable",instance_id:e,status:t.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{});let r;throw t.status==="provisioning"?r=`\u23F3 Brain instance "${t.name}" is still starting up.
9
+ \u2022 Reach us at support@cachly.dev.`);const t=ne.get(e);return t||_n(To,e,()=>Eo(e))}const To=new Map;async function Eo(e){W("verbindung: Instanz abfragen");let t=await P(`/api/v1/instances/${e}`);if(W(`verbindung: Instanz ${t.status}`),t=await xn(t,()=>P(`/api/v1/instances/${e}`),{fristMs:Qt,melde:r=>W(`verbindung: Instanz ${r.status}`)}),t.status!=="running"){fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"instance_not_reachable",instance_id:e,status:t.status,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{});let r;throw t.status==="provisioning"?r=`\u23F3 Brain instance "${t.name}" is still starting up.
10
10
 
11
11
  First-time provisioning typically takes 1\u20133 minutes. Please retry in a moment \u2014 the instance will be ready soon.`:t.status==="failed"?r=`\u274C Brain instance "${t.name}" failed to start.
12
12
 
@@ -18,11 +18,11 @@ Update your payment method at: ${j("/billing","upgrade")}`:t.status==="pending_p
18
18
  Complete your checkout at: ${j("/instances","upgrade")}`:r=`Brain instance "${t.name}" is not reachable (status: ${t.status}).
19
19
 
20
20
  \u2022 View your instance at: ${j("/instances","instance-error")}
21
- \u2022 Run \`get_api_status\` for a full diagnostic.`,new te(ie.InvalidRequest,r)}if(!t.host||!t.port)throw new te(ie.InternalError,`Instance "${t.name}" is running but has no host/port \u2014 contact support@cachly.dev.`);let s,n=t.tls_enabled!==!1;try{const r=await N(`/api/v1/instances/${e}/connection`);s=r.password??void 0,n=r.tls_enabled!==!1,W("verbindung: Zugangsdaten da")}catch(r){const a=r instanceof Error?r.message:String(r);if(a.includes("401")||a.includes("403")||a.includes("Unauthorized"))throw new te(ie.InvalidRequest,"API key rejected \u2014 run `cachly setup` to refresh your credentials.")}const o=new Ve({host:t.host,port:t.port,password:s||void 0,commandTimeout:8e3,...n?{tls:{}}:{},lazyConnect:!0,enableReadyCheck:!0,connectTimeout:8e3,retryStrategy:Co,maxRetriesPerRequest:1,keepAlive:15e3}),c=()=>{ne.delete(e),o.disconnect()};o.on("error",c),o.on("end",c);try{await o.connect()}catch(r){o.disconnect();const a=r instanceof Error?r.message:String(r);throw fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"redis_connect_failed",instance_id:e,host:t.host,port:t.port,error:a,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{}),new te(ie.InternalError,`Could not reach Brain instance "${t.name}" (${t.host}:${t.port}).
21
+ \u2022 Run \`get_api_status\` for a full diagnostic.`,new te(ie.InvalidRequest,r)}if(!t.host||!t.port)throw new te(ie.InternalError,`Instance "${t.name}" is running but has no host/port \u2014 contact support@cachly.dev.`);let s,n=t.tls_enabled!==!1;try{const r=await P(`/api/v1/instances/${e}/connection`);s=r.password??void 0,n=r.tls_enabled!==!1,W("verbindung: Zugangsdaten da")}catch(r){const a=r instanceof Error?r.message:String(r);if(a.includes("401")||a.includes("403")||a.includes("Unauthorized"))throw new te(ie.InvalidRequest,"API key rejected \u2014 run `cachly setup` to refresh your credentials.")}const o=new Ve({host:t.host,port:t.port,password:s||void 0,commandTimeout:8e3,...n?{tls:{}}:{},lazyConnect:!0,enableReadyCheck:!0,connectTimeout:8e3,retryStrategy:Co,maxRetriesPerRequest:1,keepAlive:15e3}),c=()=>{ne.delete(e),o.disconnect()};o.on("error",c),o.on("end",c);try{await o.connect()}catch(r){o.disconnect();const a=r instanceof Error?r.message:String(r);throw fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json",...y?{Authorization:`Bearer ${y}`}:{}},body:JSON.stringify({event:"redis_connect_failed",instance_id:e,host:t.host,port:t.port,error:a,version:D}),signal:AbortSignal.timeout(3e3)}).catch(()=>{}),new te(ie.InternalError,`Could not reach Brain instance "${t.name}" (${t.host}:${t.port}).
22
22
 
23
23
  \u2022 Check your network connection
24
24
  \u2022 Run \`get_api_status\` to verify instance status
25
- \u2022 Technical detail: ${a}`)}return ne.set(e,o),W("verbindung: Valkey verbunden"),o}async function N(e,t={},s=!1){s||De(Se(y))!=="none"&&await Re(),Ht(y);const n=Number(process.env.CACHLY_API_TIMEOUT_MS??15e3),o=await fetch(`${x}${e}`,{...t,signal:AbortSignal.timeout(n),headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`,...t.headers}});if(!o.ok){if(o.status===401&&!s&&(Ie=0,await Re()))return N(e,t,!0);const r=(await o.json().catch(()=>({error:o.statusText}))).error??o.statusText;Mt(o.status,r)}if(o.status!==204)return o.json()}import{handleBrainTool as Io}from"./handlers/brain.js";import{handleContextTool as Ro}from"./handlers/context.js";import{handleInstanceTool as jo}from"./handlers/instances.js";import{handleCacheTool as Bo}from"./handlers/cache.js";import{handleTeamTool as Lo}from"./handlers/team.js";import{handleRoadmapTool as Oo}from"./handlers/roadmap.js";import{handleAdvancedTool as Po}from"./handlers/advanced.js";import{handleSyndicateTool as No}from"./handlers/syndicate.js";import{handleFedbrainTool as je,_lastBrainFromGitCounts as we}from"./handlers/fedbrain.js";import{extractFirstRecallProof as Ho,renderFirstRecallProof as Mo}from"./first-recall-proof.js";import{installClsPostCommitHook as ot,CLS_HOOK_VERSION as nt}from"./cls-hook.js";import{CLAUDE_MD_MARKER_START as st,CLAUDE_MD_MARKER_END as it,EDITOR_FILES as me,ANWEISUNGS_DATEIEN as Do,setzeAnweisungsblock as Uo}from"./projektdateien.js";import{uninstallBefehl as Jo}from"./uninstall.js";import{gitLesen as rt}from"./git-ohne-shell.js";import{browserAdresse as zo,fuerCmd as Fo}from"./browser-adresse.js";import{installAmbientHooks as at,installCursorHooks as Wo,installCopilotHooks as Yo,installCodexHooks as Ko,installGeminiHooks as qo,AMBIENT_HOOK_VERSION as ct,COPILOT_HOOKS_DATEI as Go,CODEX_HOOKS_DATEI as Vo,GEMINI_SETTINGS_DATEI as Zo}from"./ambient-hooks.js";import{hookHauptlauf as Qo,auffrischenHauptlauf as Xo,startwissenImportHauptlauf as en}from"./ambient-hook.js";import{STARTWISSEN_IMPORT as tn}from"./startwissen-hook.js";import{rahmeAntwort as on}from"./antwort-rahmen.js";import{appendLedgerEntry as nn,readLedger as lt,defaultLedgerPath as sn,reportLedgerEntry as rn}from"./ambient-ledger.js";import{resolveApiKey as Be,saveApiKey as Q,saveInstanceId as dt,readSavedApiKey as Le,readInstanceId as ut}from"./credentials.js";import{KEYCLOAK_BASIS as pt,istTestSchluessel as an,waehleTestSchluessel as cn,starteKeycloakAnmeldung as ln,warteAufKeycloakAnmeldung as dn,uebernimm as un,brainImKonto as pn,erfolgsText as mn,fehlerText as gn,ersetzeSchluessel as fn}from"./uebernahme.js";import{WARTE_TAKT_MS as hn,auftragLiegt as mt,nimmAuftrag as yn,sichereKonto as bn,sperreLiegt as vn,startwissenEingeschaltet as gt}from"./konto-anlegen.js";import{sichereZugang as wn,echterWert as xe}from"./zugang.js";import{zeitpunkt as W}from"./zeitmessung.js";import{warteAufLaufendeInstanz as xn,gemeinsamerAufbau as _n}from"./instanz-warten.js";import{merkeNeuesBrain as Oe,startetLautLetztemBlick as $n}from"./leeres-brain.js";import{starteStartwissen as kn,startwissenGestartet as Sn,beanspruchStartwissen as An,holeStartwissenHinweis as Cn,waehleProjektOrdner as Tn,startvorratErlaubt as En}from"./startwissen.js";import{eigeneFassung as In,pruefeNeueFassung as Rn,holeNeueFassungHinweis as jn}from"./neue-fassung.js";import{beiStdinEnde as Bn}from"./stdin-ende.js";import{merkeWerkzeugAufruf as Ln,starteBrandWachhund as On}from"./brand-wachhund.js";import{sichtbareWerkzeuge as Pn,VERTEILER as ft}from"./werkzeug-auswahl.js";import{buildLessonsMarkdown as Nn,buildLessonsJsonl as Hn,vonRohLektion as Mn}from"./brain-export.js";import{detectEditor as Dn}from"./editor.js";import{milestoneSent as ht,markMilestoneSent as yt}from"./funnel-milestones.js";import{kostprobeUebrig as Un,kostprobeVerbrauchen as Jn,kostprobeHinweis as zn,schrankeNachKostproben as Fn}from"./kostprobe.js";import{netBalance as Wn}from"./ambient-recall.js";import{handleShareTool as Pe}from"./handlers/share.js";import{handleVizTool as Yn}from"./handlers/viz.js";import{commitArt as Kn,istRueckbau as qn,zaehleLektionen as Gn}from"./commit-art.js";import{TOOLS as ge}from"./tools.js";let bt=!1,_e=!1;function vt(){return Dn()}function Vn(e){if(!e)return null;const t=e.match(/\*\*💡\s+([^*]+)\*\*/),s=e.match(/^>\s+(.+)$/m);if(!t||!s)return null;const n=t[1].trim(),o=s[1].trim();return!n||!o?null:{topic:n,what:o}}function Zn(e){try{const t=e.split(".");if(t.length!==3)return;const s=JSON.parse(Buffer.from(t[1],"base64url").toString("utf-8"));if(!s.sub)return;let n=2166136261;for(let o=0;o<s.sub.length;o++)n^=s.sub.charCodeAt(o),n=n*16777619>>>0;return n.toString(16).padStart(8,"0")+s.sub.length.toString(16).padStart(4,"0")}catch{return}}function S(e,t,s){if(process.env.CACHLY_NO_TELEMETRY==="1")return;const n=y?Zn(y):void 0;fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:e,version:D,editor:vt(),...y?{jwt:y}:{},...n?{user_fingerprint:n}:{},...s?{metrics:s}:{},...t}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}function Qn(e,t){return rn({apiUrl:x,jwt:y,instanceId:e},t)}async function Xn(e){if(!bt&&process.env.CACHLY_NO_TELEMETRY!=="1"){bt=!0;try{await fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"first_call_no_jwt",version:D,editor:vt(),tool:e}),signal:AbortSignal.timeout(3e3)})}catch{}}}const es=new Set(["causal_trace","brain_predict","brain_plan","brain_predict_failures","team_learn","team_confirm","team_recall","team_synthesize","team_crystallize","global_learn","global_recall"]),ts={causal_trace:"Causal root-cause tracing \u2014 follow the failure chain to the real cause, not just the symptom.",brain_predict:"Predictive risk \u2014 your Brain warns you what will break *before* you run it.",brain_plan:"Generative planning \u2014 turn a goal into an ordered, risk-aware plan from your own history.",brain_predict_failures:"Failure prediction \u2014 catch CI/build breakage before it happens.",team_learn:"Team Brain \u2014 one shared memory across your whole team.",team_confirm:"Team Brain \u2014 peer + senior review that raises lesson trust.",team_recall:"Team Brain \u2014 recall everything your teammates have already solved.",team_synthesize:"Team Brain \u2014 synthesize collective knowledge across authors.",team_crystallize:"Team Brain \u2014 compress your team's wisdom into a shareable crystal.",global_learn:"Team Brain \u2014 contribute to your organization's shared memory.",global_recall:"Team Brain \u2014 recall across your entire organization."},wt=j("/billing","upgrade"),xt=new Map;async function os(e){const t=xt.get(e);if(t&&t.expiresAt>Date.now())return t.info;try{const n=((await N(`/api/v1/instances/${e}`))?.tier??"free").toLowerCase(),o={tier:n,isFree:n==="free"||n===""};return xt.set(e,{info:o,expiresAt:Date.now()+6e4}),o}catch{return{tier:"unknown",isFree:!1}}}async function ns(e,t){if(!es.has(e)||!t)return null;const{isFree:s}=await os(t);if(!s)return null;const n=ts[e]??"A Premium intelligence feature.";if(Un(e)){const o=Jn(e);return{kostprobe:zn(e,o,wt)}}return{sperre:Fn(e,n,wt)}}async function ss(e,t){try{await(await H(e)).hincrby(zt(e),t,1)}catch{}}async function is(e,t,s){if(Ft(t))try{const n=await H(e),o=Kt(s);await n.incrby(Wt(e),o?Yt(s):0),await n.hincrby(Ue(e),"abrufe",1),o&&await n.hincrby(Ue(e),"treffer",1)}catch{}}async function rs(e){const t=await co();return t?(G=t,S("device_flow_started",{tool:e}),ce(t.verifyUrl,(s,n)=>{if(s){S("device_browser_opened",{stelle:"tool"});return}S("device_browser_failed",{reason:n??"unknown",stelle:"tool"}),process.stderr.write(`
25
+ \u2022 Technical detail: ${a}`)}return ne.set(e,o),W("verbindung: Valkey verbunden"),o}async function P(e,t={},s=!1){s||De(Se(y))!=="none"&&await Re(),Ht(y);const n=Number(process.env.CACHLY_API_TIMEOUT_MS??15e3),o=await fetch(`${x}${e}`,{...t,signal:AbortSignal.timeout(n),headers:{"Content-Type":"application/json",Authorization:`Bearer ${y}`,...t.headers}});if(!o.ok){if(o.status===401&&!s&&(Ie=0,await Re()))return P(e,t,!0);const r=(await o.json().catch(()=>({error:o.statusText}))).error??o.statusText;Mt(o.status,r)}if(o.status!==204)return o.json()}import{handleBrainTool as Io}from"./handlers/brain.js";import{handleContextTool as Ro}from"./handlers/context.js";import{handleInstanceTool as jo}from"./handlers/instances.js";import{handleCacheTool as Bo}from"./handlers/cache.js";import{handleTeamTool as Lo}from"./handlers/team.js";import{handleRoadmapTool as Oo}from"./handlers/roadmap.js";import{handleAdvancedTool as No}from"./handlers/advanced.js";import{handleSyndicateTool as Po}from"./handlers/syndicate.js";import{handleFedbrainTool as je,_lastBrainFromGitCounts as we}from"./handlers/fedbrain.js";import{extractFirstRecallProof as Ho,renderFirstRecallProof as Mo}from"./first-recall-proof.js";import{installClsPostCommitHook as ot,CLS_HOOK_VERSION as nt}from"./cls-hook.js";import{CLAUDE_MD_MARKER_START as st,CLAUDE_MD_MARKER_END as it,EDITOR_FILES as me,ANWEISUNGS_DATEIEN as Do,setzeAnweisungsblock as Uo}from"./projektdateien.js";import{uninstallBefehl as Jo}from"./uninstall.js";import{gitLesen as rt}from"./git-ohne-shell.js";import{browserAdresse as zo,fuerCmd as Fo}from"./browser-adresse.js";import{installAmbientHooks as at,installCursorHooks as Wo,installCopilotHooks as Yo,installCodexHooks as Ko,installGeminiHooks as qo,AMBIENT_HOOK_VERSION as ct,COPILOT_HOOKS_DATEI as Go,CODEX_HOOKS_DATEI as Vo,GEMINI_SETTINGS_DATEI as Zo}from"./ambient-hooks.js";import{hookHauptlauf as Qo,auffrischenHauptlauf as Xo,startwissenImportHauptlauf as en}from"./ambient-hook.js";import{STARTWISSEN_IMPORT as tn}from"./startwissen-hook.js";import{rahmeAntwort as on}from"./antwort-rahmen.js";import{appendLedgerEntry as nn,readLedger as lt,defaultLedgerPath as sn,reportLedgerEntry as rn}from"./ambient-ledger.js";import{resolveApiKey as Be,saveApiKey as Q,saveInstanceId as dt,readSavedApiKey as Le,readInstanceId as ut}from"./credentials.js";import{KEYCLOAK_BASIS as pt,istTestSchluessel as an,waehleTestSchluessel as cn,starteKeycloakAnmeldung as ln,warteAufKeycloakAnmeldung as dn,uebernimm as un,brainImKonto as pn,erfolgsText as mn,fehlerText as gn,ersetzeSchluessel as fn}from"./uebernahme.js";import{WARTE_TAKT_MS as hn,auftragLiegt as mt,nimmAuftrag as yn,sichereKonto as bn,sperreLiegt as vn,startwissenEingeschaltet as gt}from"./konto-anlegen.js";import{sichereZugang as wn,echterWert as xe}from"./zugang.js";import{zeitpunkt as W}from"./zeitmessung.js";import{warteAufLaufendeInstanz as xn,gemeinsamerAufbau as _n}from"./instanz-warten.js";import{merkeNeuesBrain as Oe,startetLautLetztemBlick as $n}from"./leeres-brain.js";import{starteStartwissen as kn,startwissenGestartet as Sn,beanspruchStartwissen as An,holeStartwissenHinweis as Cn,waehleProjektOrdner as Tn,startvorratErlaubt as En}from"./startwissen.js";import{eigeneFassung as In,pruefeNeueFassung as Rn,holeNeueFassungHinweis as jn}from"./neue-fassung.js";import{beiStdinEnde as Bn}from"./stdin-ende.js";import{merkeWerkzeugAufruf as Ln,starteBrandWachhund as On}from"./brand-wachhund.js";import{sichtbareWerkzeuge as Nn,VERTEILER as ft}from"./werkzeug-auswahl.js";import{buildLessonsMarkdown as Pn,buildLessonsJsonl as Hn,vonRohLektion as Mn}from"./brain-export.js";import{detectEditor as Dn}from"./editor.js";import{milestoneSent as ht,markMilestoneSent as yt}from"./funnel-milestones.js";import{kostprobeUebrig as Un,kostprobeVerbrauchen as Jn,kostprobeHinweis as zn,schrankeNachKostproben as Fn}from"./kostprobe.js";import{netBalance as Wn}from"./ambient-recall.js";import{handleShareTool as Ne}from"./handlers/share.js";import{handleVizTool as Yn}from"./handlers/viz.js";import{commitArt as Kn,istRueckbau as qn,zaehleLektionen as Gn}from"./commit-art.js";import{TOOLS as ge}from"./tools.js";let bt=!1,_e=!1;function vt(){return Dn()}function Vn(e){if(!e)return null;const t=e.match(/\*\*💡\s+([^*]+)\*\*/),s=e.match(/^>\s+(.+)$/m);if(!t||!s)return null;const n=t[1].trim(),o=s[1].trim();return!n||!o?null:{topic:n,what:o}}function Zn(e){try{const t=e.split(".");if(t.length!==3)return;const s=JSON.parse(Buffer.from(t[1],"base64url").toString("utf-8"));if(!s.sub)return;let n=2166136261;for(let o=0;o<s.sub.length;o++)n^=s.sub.charCodeAt(o),n=n*16777619>>>0;return n.toString(16).padStart(8,"0")+s.sub.length.toString(16).padStart(4,"0")}catch{return}}function S(e,t,s){if(process.env.CACHLY_NO_TELEMETRY==="1")return;const n=y?Zn(y):void 0;fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:e,version:D,editor:vt(),...y?{jwt:y}:{},...n?{user_fingerprint:n}:{},...s?{metrics:s}:{},...t}),signal:AbortSignal.timeout(3e3)}).catch(()=>{})}function Qn(e,t){return rn({apiUrl:x,jwt:y,instanceId:e},t)}async function Xn(e){if(!bt&&process.env.CACHLY_NO_TELEMETRY!=="1"){bt=!0;try{await fetch(`${x}/api/v1/telemetry/mcp`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({event:"first_call_no_jwt",version:D,editor:vt(),tool:e}),signal:AbortSignal.timeout(3e3)})}catch{}}}const es=new Set(["causal_trace","brain_predict","brain_plan","brain_predict_failures","team_learn","team_confirm","team_recall","team_synthesize","team_crystallize","global_learn","global_recall"]),ts={causal_trace:"Causal root-cause tracing \u2014 follow the failure chain to the real cause, not just the symptom.",brain_predict:"Predictive risk \u2014 your Brain warns you what will break *before* you run it.",brain_plan:"Generative planning \u2014 turn a goal into an ordered, risk-aware plan from your own history.",brain_predict_failures:"Failure prediction \u2014 catch CI/build breakage before it happens.",team_learn:"Team Brain \u2014 one shared memory across your whole team.",team_confirm:"Team Brain \u2014 peer + senior review that raises lesson trust.",team_recall:"Team Brain \u2014 recall everything your teammates have already solved.",team_synthesize:"Team Brain \u2014 synthesize collective knowledge across authors.",team_crystallize:"Team Brain \u2014 compress your team's wisdom into a shareable crystal.",global_learn:"Team Brain \u2014 contribute to your organization's shared memory.",global_recall:"Team Brain \u2014 recall across your entire organization."},wt=j("/billing","upgrade"),xt=new Map;async function os(e){const t=xt.get(e);if(t&&t.expiresAt>Date.now())return t.info;try{const n=((await P(`/api/v1/instances/${e}`))?.tier??"free").toLowerCase(),o={tier:n,isFree:n==="free"||n===""};return xt.set(e,{info:o,expiresAt:Date.now()+6e4}),o}catch{return{tier:"unknown",isFree:!1}}}async function ns(e,t){if(!es.has(e)||!t)return null;const{isFree:s}=await os(t);if(!s)return null;const n=ts[e]??"A Premium intelligence feature.";if(Un(e)){const o=Jn(e);return{kostprobe:zn(e,o,wt)}}return{sperre:Fn(e,n,wt)}}async function ss(e,t){try{await(await H(e)).hincrby(zt(e),t,1)}catch{}}async function is(e,t,s){if(Ft(t))try{const n=await H(e),o=Kt(s);await n.incrby(Wt(e),o?Yt(s):0),await n.hincrby(Ue(e),"abrufe",1),o&&await n.hincrby(Ue(e),"treffer",1)}catch{}}async function rs(e){const t=await co();return t?(G=t,S("device_flow_started",{tool:e}),ce(t.verifyUrl,(s,n)=>{if(s){S("device_browser_opened",{stelle:"tool"});return}S("device_browser_failed",{reason:n??"unknown",stelle:"tool"}),process.stderr.write(`
26
26
  cachly: could not open a browser (${n??"unknown"}).
27
27
  cachly: open this yourself to finish signing in:
28
28
  cachly: ${t.verifyUrl}
@@ -31,7 +31,7 @@ cachly: code ${t.userCode}
31
31
  `)}),uo(t),["\u{1F9E0} **cachly AI Brain \u2014 the user must sign in once.**","","**Show the following link and code to the user verbatim \u2014 they cannot","continue without them.**","",`\u{1F449} **${t.verifyUrl}**`,"",`Code: **${t.userCode}**`,"","A browser may have opened automatically with the code pre-filled. If it","did not, the link above is the whole step.","","Once signed in, the Brain activates on its own \u2014 no further action, no","restart. The next request arrives brain-powered.","",`\u2728 ${ge.length} MCP tools \xB7 GDPR \xB7 EU servers \xB7 free tier, no credit card`].join(`
32
32
  `)):["\u{1F9E0} **cachly AI Brain \u2014 Setup required**","","Run the setup wizard once in your terminal:"," ```"," npx @cachly-dev/mcp-server@latest autopilot"," ```","",`Or get your API key at: ${j("/setup-ai","ambient-signin")}`,"","\u2728 Free tier includes: 1 Brain instance, persistent memory, semantic search."].join(`
33
33
  `)}async function as(e){if(!e)return!0;if(Sn(e))return!1;try{return await An(await H(e),"sitzungsstart")}catch{return!0}}async function z(e,t){if(!y&&await Ee(eo))return z(e,t);if(!y){if(Xn(e),G){const i=await Xe(G);return i==="done"?z(e,t):i==="expired"?(S("device_flow_failed",{reason:"timeout"}),G=null,"\u231B **Authentication timed out.** Please call any tool again to restart the sign-in flow."):["\u23F3 **Signing you in\u2026**","",`Finish in your browser: **${G.verifyUrl}**`,`Code: **${G.userCode}**`,"","This completes automatically once you sign in \u2014 no need to come back here."].join(`
34
- `)}return wn({schluessel:y,konfigurierteInstanz:P,aufrufInstanz:t.instance_id,werkzeugName:e,holeSofortTest:async()=>{W("sofort-test: Anfang");const i=await bn({apiUrl:x,version:D,fristMs:to}),d=i.art==="angelegt"?i.test:i.art==="vorhanden"&&i.instanzId?{apiKey:i.apiKey,instanzId:i.instanzId}:null;return W(`sofort-test: ${d?"Brain angelegt":"kein Test"}`),d&&Oe(d.instanzId,re(),Te()),d},ablagen:{setzeSchluessel:i=>{y=i},setEmbedJwt:le,saveApiKey:i=>Q(i),persistApiKeyToConfig:ue,merkeInstanz:i=>{P=i,Z=0},persistInstanceIdToConfig:pe},meldeEreignis:S,werkzeug:()=>z(e,t),anmelden:()=>rs(e),neuesBrain:Ce})}if(!t.instance_id){const i=await Qe();i&&(t={...t,instance_id:i})}const s=await ns(e,t.instance_id);let n="";if(s!==null){if("sperre"in s)return S("premium_gate_hit",{tool:e,instance_id:t.instance_id??""}),s.sperre;n=s.kostprobe,S("premium_taste_used",{tool:e,instance_id:t.instance_id??""})}typeof t.instance_id=="string"&&t.instance_id&&ss(t.instance_id,e),W(`werkzeug ${e}: Zugang und Tarif geklaert`);const o=await Io(e,t,H,N);if(W(`werkzeug ${e}: Brain-Werkzeug fertig`),o!==null){typeof t.instance_id=="string"&&t.instance_id&&is(t.instance_id,e,String(o??"")),!_e&&y&&(_e=!0,ht("first_call_success")||(yt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??P??""})));const i=t.instance_id??P??"",d=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="recall_best_solution")S("recall_best_solution",d);else if(e==="learn_from_attempts")S("learn_from_attempts",d);else if(e==="session_start"){S("session_start",d,{born_at:void 0,recalls_total:void 0,starter_seeded:!1});const h=typeof o=="object"&&o!==null&&"content"in o?JSON.stringify(o):String(o??""),T=h.includes("Welcome! Your AI Brain is live.");if(!$n(i)){if(!T&&h.length>100)S("recall_best_solution",d);else if(T&&t.workspace_path&&await as(i))try{const E=await je("brain_from_git",{instance_id:i,repo_path:t.workspace_path,limit:50},H,N);if(E!==null){S("brain_from_git",{...d,...we??{}}),S("recall_best_solution",d);let C="";if((we?.total??0)===0)try{const O=await Pe("brain_seed_starter",{instance_id:i},H,N);O&&(S("brain_seed_starter",{...d,auto:!0},{seeded_count:16,auto:!0}),C=`
34
+ `)}return wn({schluessel:y,konfigurierteInstanz:N,aufrufInstanz:t.instance_id,werkzeugName:e,holeSofortTest:async()=>{W("sofort-test: Anfang");const i=await bn({apiUrl:x,version:D,fristMs:to}),d=i.art==="angelegt"?i.test:i.art==="vorhanden"&&i.instanzId?{apiKey:i.apiKey,instanzId:i.instanzId}:null;return W(`sofort-test: ${d?"Brain angelegt":"kein Test"}`),d&&Oe(d.instanzId,re(),Te()),d},ablagen:{setzeSchluessel:i=>{y=i},setEmbedJwt:le,saveApiKey:i=>Q(i),persistApiKeyToConfig:ue,merkeInstanz:i=>{N=i,Z=0},persistInstanceIdToConfig:pe},meldeEreignis:S,werkzeug:()=>z(e,t),anmelden:()=>rs(e),neuesBrain:Ce})}if(!t.instance_id){const i=await Qe();i&&(t={...t,instance_id:i})}const s=await ns(e,t.instance_id);let n="";if(s!==null){if("sperre"in s)return S("premium_gate_hit",{tool:e,instance_id:t.instance_id??""}),s.sperre;n=s.kostprobe,S("premium_taste_used",{tool:e,instance_id:t.instance_id??""})}typeof t.instance_id=="string"&&t.instance_id&&ss(t.instance_id,e),W(`werkzeug ${e}: Zugang und Tarif geklaert`);const o=await Io(e,t,H,P);if(W(`werkzeug ${e}: Brain-Werkzeug fertig`),o!==null){typeof t.instance_id=="string"&&t.instance_id&&is(t.instance_id,e,String(o??"")),!_e&&y&&(_e=!0,ht("first_call_success")||(yt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??N??""})));const i=t.instance_id??N??"",d=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="recall_best_solution")S("recall_best_solution",d);else if(e==="learn_from_attempts")S("learn_from_attempts",d);else if(e==="session_start"){S("session_start",d,{born_at:void 0,recalls_total:void 0,starter_seeded:!1});const h=typeof o=="object"&&o!==null&&"content"in o?JSON.stringify(o):String(o??""),T=h.includes("Welcome! Your AI Brain is live.");if(!$n(i)){if(!T&&h.length>100)S("recall_best_solution",d);else if(T&&t.workspace_path&&await as(i))try{const E=await je("brain_from_git",{instance_id:i,repo_path:t.workspace_path,limit:50},H,P);if(E!==null){S("brain_from_git",{...d,...we??{}}),S("recall_best_solution",d);let C="";if((we?.total??0)===0)try{const O=await Ne("brain_seed_starter",{instance_id:i},H,P);O&&(S("brain_seed_starter",{...d,auto:!0},{seeded_count:16,auto:!0}),C=`
35
35
  ---
36
36
  `+String(O))}catch{}const I=String(E),$=we?.total??0,k=$>0?`
37
37
  \u2705 **Brain bootstrapped from git \u2014 ${$} lesson${$===1?"":"s"} loaded.** Your AI already knows your history.`:"";if(I||C||k)return String(o)+k+`
@@ -42,13 +42,13 @@ cachly: code ${t.userCode}
42
42
  > Run \`brain_from_git(instance_id="`+i+'", repo_path="'+String(t.workspace_path)+'")` manually to seed it.\n> Or try `brain_seed_starter` to load 16 universal engineering lessons instantly.'}}}else if(e==="session_end")S("session_end",d);else if(e==="smart_recall"){const h=typeof o=="object"&&o!==null&&"content"in o?JSON.stringify(o):String(o??""),T=h.length>50&&!h.includes("No lessons found")&&!h.includes("no lessons")&&!h.includes("No matches found");if(S("smart_recall",d,{hit:T,topic:String(t.query??"").slice(0,80)}),T&&S("recall_best_solution",d),ae&&typeof o=="string")return`> \u26A0\uFE0F **Brain auth degraded** \u2014 ${ae.split(`
43
43
  `)[0]}
44
44
 
45
- ${o}`}return o}const c=await Ro(e,t,H,N);if(c!==null)return!_e&&y&&(_e=!0,ht("first_call_success")||(yt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??P??""}))),c;const r=await jo(e,t,H,N);if(r!==null)return r;const a=await Bo(e,t,H,N);if(a!==null)return a;const u=i=>n?i+n:i,m=await Lo(e,t,H,N);if(m!==null)return u(m);const l=await Oo(e,t,H,N);if(l!==null)return l;const g=await Po(e,t,H,N);if(g!==null)return u(g);const w=await No(e,t,H,N);if(w!==null){if(e==="brain_predict"){const i=t.instance_id??P??"";S("brain_predict",y?{api_key:y,instance_id:i}:{instance_id:i})}return u(w)}const v=await Pe(e,t,H,N);if(v!==null)return v;const b=await Yn(e,t,H,N);if(b!==null)return b;const p=await je(e,t,H,N);if(p!==null){const i=t.instance_id??P??"",d=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="brain_from_git"){const h=we;S("brain_from_git",{...d,...h??{}},h?{fixes:h.fixes,features:h.features,refactors:h.refactors,total:h.total}:void 0)}else e==="brain_predict_failures"&&S("brain_predict_failures",d);return p}switch(e){case"get_api_status":{let i="unknown";try{const E=await fetch(`${x}/health`,{signal:AbortSignal.timeout(8e3)});if(E.ok){const A=await E.json();i=`${A.status??"ok"} (db: ${A.db??"?"})`}else i=`HTTP ${E.status}`}catch(E){i=`unreachable: ${E.message}`}if(!y)return["\u{1F4E1} **cachly API Status**","",` \u{1F310} API: ${x}`,` \u{1F493} Health: ${i}`," \u{1F511} Auth: \u274C CACHLY_JWT not set","",`\u{1F4A1} Get your API token at ${j("/instances","api-status")} \u2192 Settings \u2192 API Token`].join(`
45
+ ${o}`}return o}const c=await Ro(e,t,H,P);if(c!==null)return!_e&&y&&(_e=!0,ht("first_call_success")||(yt("first_call_success"),S("first_call_success",{tool:e,instance_id:t.instance_id??N??""}))),c;const r=await jo(e,t,H,P);if(r!==null)return r;const a=await Bo(e,t,H,P);if(a!==null)return a;const u=i=>n?i+n:i,m=await Lo(e,t,H,P);if(m!==null)return u(m);const l=await Oo(e,t,H,P);if(l!==null)return l;const g=await No(e,t,H,P);if(g!==null)return u(g);const w=await Po(e,t,H,P);if(w!==null){if(e==="brain_predict"){const i=t.instance_id??N??"";S("brain_predict",y?{api_key:y,instance_id:i}:{instance_id:i})}return u(w)}const v=await Ne(e,t,H,P);if(v!==null)return v;const b=await Yn(e,t,H,P);if(b!==null)return b;const p=await je(e,t,H,P);if(p!==null){const i=t.instance_id??N??"",d=y?{api_key:y,instance_id:i}:{instance_id:i};if(e==="brain_from_git"){const h=we;S("brain_from_git",{...d,...h??{}},h?{fixes:h.fixes,features:h.features,refactors:h.refactors,total:h.total}:void 0)}else e==="brain_predict_failures"&&S("brain_predict_failures",d);return p}switch(e){case"get_api_status":{let i="unknown";try{const E=await fetch(`${x}/health`,{signal:AbortSignal.timeout(8e3)});if(E.ok){const A=await E.json();i=`${A.status??"ok"} (db: ${A.db??"?"})`}else i=`HTTP ${E.status}`}catch(E){i=`unreachable: ${E.message}`}if(!y)return["\u{1F4E1} **cachly API Status**","",` \u{1F310} API: ${x}`,` \u{1F493} Health: ${i}`," \u{1F511} Auth: \u274C CACHLY_JWT not set","",`\u{1F4A1} Get your API token at ${j("/instances","api-status")} \u2192 Settings \u2192 API Token`].join(`
46
46
  `);let d="\u274C invalid JWT format";try{const E=y.split(".");if(E.length===3){const A=JSON.parse(Buffer.from(E[1],"base64url").toString("utf-8")),C=A.sub??"(unknown)",I=A.iss??"(unknown)",$=I.includes("keycloak")?"Keycloak":"OIDC",k=A.exp?new Date(A.exp*1e3):null,O=k?k<new Date:!1;d=["\u2705 JWT decoded",` Sub (user ID): ${C}`,` Provider: ${$}`,` Issuer: ${I}`,` Expires: ${k?k.toISOString():"never"} ${O?"\u26A0\uFE0F EXPIRED \u2013 get a new token!":"\u2705"}`].join(`
47
- `)}}catch{d="\u274C JWT decode failed \u2013 check CACHLY_JWT format"}let h="";try{const A=(await N("/api/v1/instances")).data??[];if(A.length===0)h=`
47
+ `)}}catch{d="\u274C JWT decode failed \u2013 check CACHLY_JWT format"}let h="";try{const A=(await P("/api/v1/instances")).data??[];if(A.length===0)h=`
48
48
 
49
49
  \u{1F9E0} **Brain Instances:** none \u2014 create one at ${j("/instances","api-status")}`;else{const C=[`
50
50
 
51
- \u{1F9E0} **Brain Instances:**`];for(const I of A){const $=I.status==="running"?"\u{1F7E2}":I.status==="provisioning"?"\u{1F7E1}":"\u{1F534}",k=I.id===P?" \u2190 active":"";if(C.push(` ${$} **${I.name}** (\`${I.id}\`) \xB7 ${I.status}${k}`),I.status==="running"&&I.host){const O=ne.get(I.id);if(O)try{await O.ping(),C.push(" \u{1F493} Redis: connected")}catch{C.push(" \u26A0\uFE0F Redis: pooled but ping failed \u2014 will reconnect on next use")}else C.push(" \u{1F4A4} Redis: not connected yet (connects on first tool use)")}else I.status==="provisioning"?C.push(" \u23F3 Still provisioning \u2014 check back in ~30 s"):I.status!=="running"&&C.push(` \u274C Not reachable (status: ${I.status})`)}h=C.join(`
51
+ \u{1F9E0} **Brain Instances:**`];for(const I of A){const $=I.status==="running"?"\u{1F7E2}":I.status==="provisioning"?"\u{1F7E1}":"\u{1F534}",k=I.id===N?" \u2190 active":"";if(C.push(` ${$} **${I.name}** (\`${I.id}\`) \xB7 ${I.status}${k}`),I.status==="running"&&I.host){const O=ne.get(I.id);if(O)try{await O.ping(),C.push(" \u{1F493} Redis: connected")}catch{C.push(" \u26A0\uFE0F Redis: pooled but ping failed \u2014 will reconnect on next use")}else C.push(" \u{1F4A4} Redis: not connected yet (connects on first tool use)")}else I.status==="provisioning"?C.push(" \u23F3 Still provisioning \u2014 check back in ~30 s"):I.status!=="running"&&C.push(` \u274C Not reachable (status: ${I.status})`)}h=C.join(`
52
52
  `)}}catch(E){h=`
53
53
 
54
54
  \u{1F9E0} **Brain Instances:** could not fetch \u2014 ${E.message}`}await Re();const T=Se(y),L=T.state==="long_lived"?"\u{1F6E1}\uFE0F Self-healing: \u2705 long-lived API key (won't expire silently)":T.state==="healthy"?`\u{1F6E1}\uFE0F Self-healing: \u2705 token valid${T.expiresInMs?` (${Math.round(T.expiresInMs/36e5)}h left)`:""}`:T.state==="near_expiry"?"\u{1F6E1}\uFE0F Self-healing: \u267B\uFE0F token near expiry \u2014 auto-refresh attempted":`\u{1F6E1}\uFE0F Self-healing: \u26A0\uFE0F ${T.message.split(`
@@ -60,7 +60,7 @@ ${o}`}return o}const c=await Ro(e,t,H,N);if(c!==null)return!_e&&y&&(_e=!0,ht("fi
60
60
  - AFTER a fix, deploy, or discovery: call learn_from_attempts so the knowledge persists.
61
61
  - BEFORE a risky op (deploy, migration, dependency bump): call brain_predict.
62
62
 
63
- The Brain instance id comes from the CACHLY_BRAIN_INSTANCE_ID environment variable.`,kt={tools:{},resources:{},prompts:{}},St=async()=>{const{katalog:e,unbekannteKernnamen:t}=Pn(ge);return t.length>0&&console.error(`cachly: ${t.length} Kernwerkzeug(e) gibt es gar nicht: ${t.join(", ")}`),{tools:e}};async function At(){return{resources:[]}}async function Ct(){return{resourceTemplates:[]}}async function Tt(){return{prompts:[]}}function cs(e){e.setRequestHandler(Ge,St),e.setRequestHandler(We,Rt),e.setRequestHandler(qe,At),e.setRequestHandler(Ke,Ct),e.setRequestHandler(Ye,Tt)}function ls(){const e=new Fe({name:"cachly-mcp",version:D},{capabilities:kt,instructions:$t});return cs(e),Et(e),e}function Et(e){const t=e.oninitialized;e.oninitialized=()=>{try{const s=e.getClientVersion();Pt(s?.name,s?.version)}catch{}t?.()}}const V=new Fe({name:"cachly-mcp",version:D},{capabilities:kt,instructions:$t});Et(V),V.setRequestHandler(Ge,St),V.setRequestHandler(qe,At),V.setRequestHandler(Ke,Ct),V.setRequestHandler(Ye,Tt);let Ne=null,fe=!1,X=null,It=0;async function ds(e){if(!fe){if(X){await X;return}X=(async()=>{fe=!0,Ne=e;try{await z("session_start",{instance_id:e,focus:"auto (MCP session)",workspace_path:process.cwd()})}catch{}finally{X=null}})(),await X,process.env.CACHLY_AUTO_INDEX!=="false"&&(async()=>{const t=await H(e),s=await t.get(`cachly:index:last_indexed:${e}`),n=1440*60*1e3;(!s||Date.now()-parseInt(s,10)>n)&&(await t.set(`cachly:index:last_indexed:${e}`,String(Date.now()),"EX",9e4),await z("index_project",{instance_id:e,dir:process.cwd(),max_files:150,ttl:86400*7,namespace:"cachly:sem:code",hintergrund:!0}))})().catch(()=>{})}}async function He(){if(!(!fe||!Ne)){fe=!1;try{await z("session_end",{instance_id:Ne,summary:`Auto-ended after ${It} tool call(s). Session was started automatically.`,files_changed:[],lessons_learned:0})}catch{}}}const Rt=async e=>{let{name:t,arguments:s}=e.params;if(t===ft){const o=s??{},c=typeof o.tool=="string"?o.tool:"";if(!c)return{content:[{type:"text",text:'cachly_tool braucht das Feld "tool" \u2014 den Namen des Werkzeugs.'}],isError:!0};const r=ge.find(a=>a.name===c);if(!r)return{content:[{type:"text",text:`Kein Werkzeug namens "${c}". Die Liste steht in der Beschreibung von ${ft}.`}],isError:!0};if(o.describe===!0)return{content:[{type:"text",text:JSON.stringify({name:r.name,description:r.description,inputSchema:r.inputSchema},null,2)}]};t=c,s=o.arguments??{}}const n=new Set(["session_start","session_start_summary","session_end","auto_learn_session"]);if(!n.has(t)&&!fe&&!X){const o=xe(s?.instance_id)||P||xe(process.env.CACHLY_BRAIN_INSTANCE_ID);o&&await ds(o).catch(()=>{})}else X&&await X.catch(()=>{});n.has(t)||It++;try{Ln(),W(`werkzeug ${t}: Anfang`);const o=await z(t,s??{});return W(`werkzeug ${t}: Antwort fertig`),{content:[{type:"text",text:on(t,o)+Cn()+jn(t)}]}}catch(o){if(o instanceof _t)return{content:[{type:"text",text:o.message}],isError:!0};if(o instanceof te)throw o;const c=o.message??String(o);throw Je("cachly","tool_error",{tool:t,error:c}).catch(()=>{}),new te(ie.InternalError,c)}};V.setRequestHandler(We,Rt),process.on("SIGTERM",async()=>{await He().catch(()=>{});for(const[,e]of ne)await e.quit().catch(()=>{});process.exit(0)}),process.on("SIGINT",async()=>{await He().catch(()=>{});for(const[,e]of ne)await e.quit().catch(()=>{});process.exit(0)}),process.on("unhandledRejection",e=>{const t=e instanceof Error?e.message:String(e);process.stderr.write(`[cachly-mcp] unhandledRejection: ${t}
63
+ The Brain instance id comes from the CACHLY_BRAIN_INSTANCE_ID environment variable.`,kt={tools:{},resources:{},prompts:{}},St=async()=>{const{katalog:e,unbekannteKernnamen:t}=Nn(ge);return t.length>0&&console.error(`cachly: ${t.length} Kernwerkzeug(e) gibt es gar nicht: ${t.join(", ")}`),{tools:e}};async function At(){return{resources:[]}}async function Ct(){return{resourceTemplates:[]}}async function Tt(){return{prompts:[]}}function cs(e){e.setRequestHandler(Ge,St),e.setRequestHandler(We,Rt),e.setRequestHandler(qe,At),e.setRequestHandler(Ke,Ct),e.setRequestHandler(Ye,Tt)}function ls(){const e=new Fe({name:"cachly-mcp",version:D},{capabilities:kt,instructions:$t});return cs(e),Et(e),e}function Et(e){const t=e.oninitialized;e.oninitialized=()=>{try{const s=e.getClientVersion();Nt(s?.name,s?.version)}catch{}t?.()}}const V=new Fe({name:"cachly-mcp",version:D},{capabilities:kt,instructions:$t});Et(V),V.setRequestHandler(Ge,St),V.setRequestHandler(qe,At),V.setRequestHandler(Ke,Ct),V.setRequestHandler(Ye,Tt);let Pe=null,fe=!1,X=null,It=0;async function ds(e){if(!fe){if(X){await X;return}X=(async()=>{fe=!0,Pe=e;try{await z("session_start",{instance_id:e,focus:"auto (MCP session)",workspace_path:process.cwd()})}catch{}finally{X=null}})(),await X,process.env.CACHLY_AUTO_INDEX!=="false"&&(async()=>{const t=await H(e),s=await t.get(`cachly:index:last_indexed:${e}`),n=1440*60*1e3;(!s||Date.now()-parseInt(s,10)>n)&&(await t.set(`cachly:index:last_indexed:${e}`,String(Date.now()),"EX",9e4),await z("index_project",{instance_id:e,dir:process.cwd(),max_files:150,ttl:86400*7,namespace:"cachly:sem:code",hintergrund:!0}))})().catch(()=>{})}}async function He(){if(!(!fe||!Pe)){fe=!1;try{await z("session_end",{instance_id:Pe,summary:`Auto-ended after ${It} tool call(s). Session was started automatically.`,files_changed:[],lessons_learned:0})}catch{}}}const Rt=async e=>{let{name:t,arguments:s}=e.params;if(t===ft){const o=s??{},c=typeof o.tool=="string"?o.tool:"";if(!c)return{content:[{type:"text",text:'cachly_tool braucht das Feld "tool" \u2014 den Namen des Werkzeugs.'}],isError:!0};const r=ge.find(a=>a.name===c);if(!r)return{content:[{type:"text",text:`Kein Werkzeug namens "${c}". Die Liste steht in der Beschreibung von ${ft}.`}],isError:!0};if(o.describe===!0)return{content:[{type:"text",text:JSON.stringify({name:r.name,description:r.description,inputSchema:r.inputSchema},null,2)}]};t=c,s=o.arguments??{}}const n=new Set(["session_start","session_start_summary","session_end","auto_learn_session"]);if(!n.has(t)&&!fe&&!X){const o=xe(s?.instance_id)||N||xe(process.env.CACHLY_BRAIN_INSTANCE_ID);o&&await ds(o).catch(()=>{})}else X&&await X.catch(()=>{});n.has(t)||It++;try{Ln(),W(`werkzeug ${t}: Anfang`);const o=await z(t,s??{});return W(`werkzeug ${t}: Antwort fertig`),{content:[{type:"text",text:on(t,o)+Cn()+jn(t)}]}}catch(o){if(o instanceof _t)return{content:[{type:"text",text:o.message}],isError:!0};if(o instanceof te)throw o;const c=o.message??String(o);throw Je("cachly","tool_error",{tool:t,error:c}).catch(()=>{}),new te(ie.InternalError,c)}};V.setRequestHandler(We,Rt),process.on("SIGTERM",async()=>{await He().catch(()=>{});for(const[,e]of ne)await e.quit().catch(()=>{});process.exit(0)}),process.on("SIGINT",async()=>{await He().catch(()=>{});for(const[,e]of ne)await e.quit().catch(()=>{});process.exit(0)}),process.on("unhandledRejection",e=>{const t=e instanceof Error?e.message:String(e);process.stderr.write(`[cachly-mcp] unhandledRejection: ${t}
64
64
  `)}),process.on("uncaughtException",e=>{process.stderr.write(`[cachly-mcp] uncaughtException: ${e?.stack??String(e)}
65
65
  `)}),process.stdout.on("error",()=>{}),process.stdin.on("error",()=>{});function us(e,t){const s=Object.entries(t).map(([n,o])=>`${n}=${o}`);return e==="codex"?{befehl:`codex mcp add cachly ${s.map(n=>`--env ${n}`).join(" ")} -- npx -y @cachly-dev/mcp-server@latest`,wo:"~/.codex/config.toml"}:e==="gemini"?{befehl:`gemini mcp add -s project ${s.map(n=>`-e ${n}`).join(" ")} cachly npx -- -y @cachly-dev/mcp-server@latest`,wo:".gemini/settings.json"}:null}const jt="https://api.cachly.dev";function se(e,t,s={}){const n={CACHLY_BRAIN_INSTANCE_ID:t};return s.includeApiKey&&(n.CACHLY_JWT=e),x&&x!==jt&&(n.CACHLY_API_URL=x),n}function ps(e,t,s){return s==="continue"?JSON.stringify({experimental:{modelContextProtocolServers:[{transport:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"]},env:se(e,t)}]}},null,2):s==="zed"?JSON.stringify({context_servers:{cachly:{command:{path:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:se(e,t)},settings:{}}}},null,2):Bt(s)?JSON.stringify({servers:{cachly:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:se(e,t)}}},null,2):JSON.stringify({mcpServers:{cachly:{command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:se(e,t)}}},null,2)}function Bt(e){return me[e]===".vscode/mcp.json"}function he(e,t){an(e)||Q(e,t)}async function Lt(e,t,s,n,o,c={}){const r={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:se(t,s)};if(!o.existsSync(e))return ps(t,s,n);let a={};try{a=JSON.parse(await o.readFile(e,"utf-8"))}catch{try{const{rename:g}=await import("node:fs/promises");await g(e,e+".bak"),process.stderr.write(`\u26A0\uFE0F ${e} was not valid JSON \u2014 backed up to ${e}.bak
66
66
  `)}catch{}}if(n==="continue"){const g=a.experimental??{},w=g.modelContextProtocolServers??[];let v;for(const p of w){const i=p.env??{};if(i.CACHLY_JWT){v=i.CACHLY_JWT;break}}v&&he(v,c);const b=w.filter(p=>{const i=p.env??{};return!i.CACHLY_JWT&&!i.CACHLY_BRAIN_INSTANCE_ID});return b.push({transport:{type:"stdio",command:"npx",args:["-y","@cachly-dev/mcp-server@latest"]},env:r.env}),a.experimental={...g,modelContextProtocolServers:b},JSON.stringify(a,null,2)}if(n==="zed"){const g=a.context_servers??{},v=g.cachly?.command?.env?.CACHLY_JWT;return v&&he(v,c),g.cachly={command:{path:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:r.env},settings:{}},a.context_servers=g,JSON.stringify(a,null,2)}if(Bt(n)){const g=a.mcpServers??void 0,v=g?.cachly?.env?.CACHLY_JWT;v&&he(v,c),g&&"cachly"in g&&(delete g.cachly,Object.keys(g).length===0&&delete a.mcpServers);const b=a.servers??{},p=b.cachly,i=p?.env?.CACHLY_JWT;return i&&he(i,c),b.cachly=p?.envFile?{type:"stdio",...r,envFile:p.envFile}:{type:"stdio",...r},a.servers=b,JSON.stringify(a,null,2)}const u=a.mcpServers??{},l=u.cachly?.env?.CACHLY_JWT;return l&&he(l,c),u.cachly=r,a.mcpServers=u,JSON.stringify(a,null,2)}function ms(e){return`${st}
@@ -135,7 +135,7 @@ ${it}`}async function Ot(e,t){const{existsSync:s}=await import("node:fs"),{resol
135
135
  \u{1F4E4} Exporting your Brain...
136
136
 
137
137
  `);try{let m=[],l="";const g=await fetch(`${x}/api/v1/instances/${u}/export`,{headers:{Authorization:`Bearer ${a}`},signal:AbortSignal.timeout(12e4)});if(g.ok){const v=await g.json();m=(v.lessons??[]).map(Mn).filter(b=>b!==null),v.complete===!1&&(l=v.note??"the server reported an incomplete read")}else if(g.status===404){const v=await fetch(`${x}/api/v1/instances/${u}/memory`,{headers:{Authorization:`Bearer ${a}`},signal:AbortSignal.timeout(8e3)});if(!v.ok)throw new Error(`memory HTTP ${v.status}`);m=((await v.json()).top_lessons??[]).map(p=>({topic:p.topic,outcome:p.outcome,severity:p.severity,tags:p.tags,whatWorked:p.what_worked,ts:p.ts,author:p.author,recallCount:p.recall_count})),l="this server has no /export endpoint yet, so this is the DASHBOARD SUMMARY: at most 50 lessons, each shortened to 120 characters. Update the server for a full export."}else throw new Error(`export HTTP ${g.status}`);m.length===0&&(console.log(` No lessons in this Brain yet \u2014 nothing to export.
138
- `),process.exit(0)),await t(r,{recursive:!0});const w=[];if(c==="md"||c==="both"){const v=s(r,"lessons.md");await e(v,Nn(m),"utf-8"),w.push(`${m.length} lesson${m.length===1?"":"s"} \u2192 ${v}`)}if(c==="jsonl"||c==="both"){const v=s(r,"lessons.jsonl");await e(v,Hn(m),"utf-8"),w.push(`${m.length} lesson${m.length===1?"":"s"} \u2192 ${v}`)}l?(console.log("\u26A0\uFE0F Export INCOMPLETE \u2014 this is not your whole Brain:"),console.log(` ${l}`),console.log("")):console.log("\u2705 Export complete:");for(const v of w)console.log(` ${v}`);console.log("")}catch(m){console.log(`
138
+ `),process.exit(0)),await t(r,{recursive:!0});const w=[];if(c==="md"||c==="both"){const v=s(r,"lessons.md");await e(v,Pn(m),"utf-8"),w.push(`${m.length} lesson${m.length===1?"":"s"} \u2192 ${v}`)}if(c==="jsonl"||c==="both"){const v=s(r,"lessons.jsonl");await e(v,Hn(m),"utf-8"),w.push(`${m.length} lesson${m.length===1?"":"s"} \u2192 ${v}`)}l?(console.log("\u26A0\uFE0F Export INCOMPLETE \u2014 this is not your whole Brain:"),console.log(` ${l}`),console.log("")):console.log("\u2705 Export complete:");for(const v of w)console.log(` ${v}`);console.log("")}catch(m){console.log(`
139
139
  \u274C Could not export your Brain: ${m.message}
140
140
  `),process.exit(1)}process.exit(0)}if(process.argv[2]==="invite"){const e=oe();e||(console.log(`
141
141
  \u26A0\uFE0F No cachly key found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot
@@ -222,7 +222,7 @@ Usage: npx @cachly-dev/mcp-server@latest init --instance-id <uuid> --api-key <ck
222
222
  `),process.exit(1));const v=us(l,se(m,u));if(v)Q(m),console.log(`
223
223
  \u{1F449} Register the MCP server once (writes ${v.wo}):`),console.log(` ${v.befehl}`);else{const i=me[l]??".mcp.json",d=o(g,i);await s(c(d),{recursive:!0});const{existsSync:h}=await import("node:fs"),T=h(d),L=T?await n(d,"utf-8").catch(()=>""):"";Q(m);const E=await Lt(d,m,u,l,{readFile:n,existsSync:h});E!==L?(await t(d,E,"utf-8"),console.log(`
224
224
  \u2705 ${T?"Updated":"Written"}: ${i}`)):console.log(`
225
- \u2713 Already configured: ${i} (no change)`)}const b=await Ot(g,u);for(const[i,d]of Object.entries(b)){const h=d==="updated"?"\u2705 Updated":d==="appended"?"\u2705 Appended to":"\u2705 Written",T=i.split(/[\\/]/).pop()??i;console.log(`${h}: ${T}`)}try{const i=await ot(g,u);i==="written"?console.log("\u2705 Written: .git/hooks/post-commit (CLS hook)"):i==="upgraded"?console.log(`\u2705 Upgraded: .git/hooks/post-commit (CLS hook \u2192 ${nt})`):i==="appended"?console.log("\u2705 Appended: .git/hooks/post-commit (CLS hook)"):i==="unchanged"&&console.log("\u2713 CLS hook already current in .git/hooks/post-commit")}catch{}if(l==="claude")try{const i=await at(g,u),d=i.scripts==="written"?"\u2705 Written":i.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${ct})`:"\u2713 Unchanged";console.log(`${d}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),i.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):i.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}catch{}(l==="cursor"||l==="copilot"||l==="codex"||l==="gemini")&&await ye(l,g,u,"");const p=((Date.now()-e)/1e3).toFixed(1);console.log(`
225
+ \u2713 Already configured: ${i} (no change)`)}const b=await Ot(g,u);for(const[i,d]of Object.entries(b)){const h=d==="updated"?"\u2705 Updated":d==="appended"?"\u2705 Appended to":"\u2705 Written",T=i.split(/[\\/]/).pop()??i;console.log(`${h}: ${T}`)}try{const i=await ot(g,u);i==="written"?console.log("\u2705 Written: .git/hooks/post-commit (CLS hook)"):i==="upgraded"?console.log(`\u2705 Upgraded: .git/hooks/post-commit (CLS hook \u2192 ${nt})`):i==="appended"?console.log("\u2705 Appended: .git/hooks/post-commit (CLS hook)"):i==="unchanged"&&console.log("\u2713 CLS hook already current in .git/hooks/post-commit")}catch{}if(l==="claude")try{const i=await at(g,u);if(i.settings==="skipped")console.log(`\u26A0\uFE0F .claude/settings.json ${i.grund??"is not valid JSON"} \u2014 left untouched, Ambient Recall hooks not wired`);else{const d=i.scripts==="written"?"\u2705 Written":i.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${ct})`:"\u2713 Unchanged";console.log(`${d}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),i.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):i.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}}catch{}(l==="cursor"||l==="copilot"||l==="codex"||l==="gemini")&&await ye(l,g,u,"");const p=((Date.now()-e)/1e3).toFixed(1);console.log(`
226
226
  \u{1F9E0} Cachly AI Brain configured for ${l==="claude"?"Claude Code":l}! (${p}s)`),console.log(v?` Run the \`mcp add\` line above, then restart ${l} \u2014 the \`cachly\` MCP tools will appear.`:" Restart your editor \u2014 the `cachly` MCP tools will appear."),console.log(" Re-run `init` anytime \u2014 it's idempotent (only writes what changed)."),console.log(`
227
227
  \u{1F4DB} Add a live badge to your README:`),console.log(` npx @cachly-dev/mcp-server@latest badge
228
228
  `),process.exit(0)}if(process.argv[2]==="status"){const e=oe(),t=F();(!e||!t)&&(console.log(`
@@ -312,7 +312,7 @@ Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
312
312
  `)}catch{}}try{const f=await ot(process.cwd(),i.id);f==="written"?console.log(`
313
313
  \u2705 CLS git hook installed \u2014 your brain will learn from every commit.`):f==="upgraded"?console.log(`
314
314
  \u2705 CLS git hook upgraded to ${nt}.`):f==="appended"&&console.log(`
315
- \u2705 CLS git hook appended to existing post-commit.`)}catch{}if(I.includes("claude"))try{const f=await at(process.cwd(),i.id),_=f.scripts==="written"?"\u2705 Written":f.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${ct})`:"\u2713 Unchanged";console.log(`${_}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),f.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):f.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}catch{}I.includes("cursor")&&await ye("cursor",process.cwd(),i.id," "),I.includes("copilot")&&await ye("copilot",process.cwd(),i.id," "),(n(o(L,".codex"))||n(o(d,".codex")))&&await ye("codex",process.cwd(),i.id," "),(n(o(L,".gemini"))||n(o(d,".gemini")))&&await ye("gemini",process.cwd(),i.id," "),y=b;const Me=Math.round((Date.now()-a)/1e3);if(k.length>0&&S("setup_config_write_failed",{instance_id:i.id,failed:k.length,succeeded:O}),S("setup_completed",{instance_id:i.id,elapsed_s:Me,config_failures:k.length}),k.length>0&&O===0){console.log(`
315
+ \u2705 CLS git hook appended to existing post-commit.`)}catch{}if(I.includes("claude"))try{const f=await at(process.cwd(),i.id);if(f.settings==="skipped")console.log(`\u26A0\uFE0F .claude/settings.json ${f.grund??"is not valid JSON"} \u2014 left untouched, Ambient Recall hooks not wired`);else{const _=f.scripts==="written"?"\u2705 Written":f.scripts==="upgraded"?`\u2705 Upgraded (\u2192 ${ct})`:"\u2713 Unchanged";console.log(`${_}: .claude/hooks/ (Ambient Recall \u2014 session briefing, per-prompt recall, file briefing, auto-learn)`),f.settings==="written"?console.log("\u2705 Written: .claude/settings.json (Ambient Recall hooks wired)"):f.settings==="merged"?console.log("\u2705 Merged: .claude/settings.json (Ambient Recall hooks wired)"):console.log("\u2713 Ambient Recall hooks already wired in .claude/settings.json")}}catch{}I.includes("cursor")&&await ye("cursor",process.cwd(),i.id," "),I.includes("copilot")&&await ye("copilot",process.cwd(),i.id," "),(n(o(L,".codex"))||n(o(d,".codex")))&&await ye("codex",process.cwd(),i.id," "),(n(o(L,".gemini"))||n(o(d,".gemini")))&&await ye("gemini",process.cwd(),i.id," "),y=b;const Me=Math.round((Date.now()-a)/1e3);if(k.length>0&&S("setup_config_write_failed",{instance_id:i.id,failed:k.length,succeeded:O}),S("setup_completed",{instance_id:i.id,elapsed_s:Me,config_failures:k.length}),k.length>0&&O===0){console.log(`
316
316
  \u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557`),console.log("\u2551 \u26A0\uFE0F Setup incomplete \u2014 no editor config was written \u2551"),console.log("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"),console.log(`
317
317
  Your Brain instance exists, but no editor knows about it yet.`),console.log(" Failed writes:");for(const f of k)console.log(` \u2022 ${f.file} \u2014 ${f.reason}`);console.log(`
318
318
  Fix the permissions above and re-run, or configure manually:`),console.log(` CACHLY_JWT=${b.slice(0,12)}\u2026 CACHLY_BRAIN_INSTANCE_ID=${i.id}`),console.log(` Docs: ${j("/docs/mcp",u)}
@@ -336,10 +336,10 @@ Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
336
336
  \u2705 Brain learned from your commits.
337
337
  `),await new Promise(a=>setTimeout(a,300))}catch(r){console.error(`
338
338
  \u274C learn-git failed: ${r.message}
339
- `),process.exit(1)}process.exit(0)}if(process.argv[2]==="ambient-recall"&&await Qo(process.argv.slice(3),process.argv[1]),process.argv[2]==="ambient-auffrischen"&&await Xo(),process.argv[2]===tn&&await en(process.argv[3]??""),process.argv[2]==="ambient-credit"){try{const e=Math.round(Number(process.argv[3]));if(Number.isFinite(e)&&e>0){const t=Math.min(e,2e4),s=process.argv.slice(4).join(" ").slice(0,200)||void 0,n={ts:new Date().toISOString(),event:"credit",injected:0,prevented:t,note:s};await nn(n),await Qn(process.env.CACHLY_BRAIN_INSTANCE_ID??P,n),console.log(`\u2705 ambient credit recorded: ${t} tokens${s?` (${s})`:""}`)}else console.error("Usage: npx @cachly-dev/mcp-server@latest ambient-credit <tokens-saved> [note]")}catch{}process.exit(0)}if(process.argv[2]==="ambient-stats"){const e=await lt(),t=Wn(e),s=e.slice(-5);if(console.log(`
339
+ `),process.exit(1)}process.exit(0)}if(process.argv[2]==="ambient-recall"&&await Qo(process.argv.slice(3),process.argv[1]),process.argv[2]==="ambient-auffrischen"&&await Xo(),process.argv[2]===tn&&await en(process.argv[3]??""),process.argv[2]==="ambient-credit"){try{const e=Math.round(Number(process.argv[3]));if(Number.isFinite(e)&&e>0){const t=Math.min(e,2e4),s=process.argv.slice(4).join(" ").slice(0,200)||void 0,n={ts:new Date().toISOString(),event:"credit",injected:0,prevented:t,note:s};await nn(n),await Qn(process.env.CACHLY_BRAIN_INSTANCE_ID??N,n),console.log(`\u2705 ambient credit recorded: ${t} tokens${s?` (${s})`:""}`)}else console.error("Usage: npx @cachly-dev/mcp-server@latest ambient-credit <tokens-saved> [note]")}catch{}process.exit(0)}if(process.argv[2]==="ambient-stats"){const e=await lt(),t=Wn(e),s=e.slice(-5);if(console.log(`
340
340
  \u{1F9E0} Ambient Recall \u2014 net-token ledger
341
341
  `),console.log(` Turns recorded: ${e.length}`),console.log(` Injected tokens: ${t.injected}`),console.log(` Prevented tokens: ${t.prevented} (agent-reported via ambient-credit)`),console.log(` NET: ${t.net>=0?"+":""}${t.net} tokens`),s.length>0){console.log(`
342
- Last entries:`);for(const n of s){const o=n.prevented>0?`+${n.prevented} prevented`:`-${n.injected} injected`;console.log(` \u2022 ${n.ts.slice(0,19)} ${n.event}: ${o}${n.note?` (${n.note})`:""}`)}}console.log(""),process.exit(0)}if(process.argv[2]==="uninstall"){const{homedir:e,tmpdir:t}=await import("node:os"),{resolve:s}=await import("node:path"),{createInterface:n}=await import("node:readline/promises"),o=process.argv.slice(3),r={projekt:s((a=>{const u=o.indexOf(`--${a}`);return u!==-1?o[u+1]:void 0})("project-dir")??"."),heim:process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??e(),tmp:t(),schluessel:oe(),instanz:F(),apiUrl:x,istTty:process.stdin.isTTY===!0&&process.stdout.isTTY===!0,ausgabe:a=>console.log(a),frage:async a=>{const u=n({input:process.stdin,output:process.stdout});try{return/^(y|yes|j|ja)$/i.test((await u.question(a)).trim())}finally{u.close()}}};process.exit(await Jo(o,r))}if(process.argv[2]==="doctor"){const{checkNodeVersion:e,checkCredential:t,checkApiReachable:s,checkAuthAccepted:n,checkInstance:o,checkVectorCoverage:c,inspectAmbientHooks:r,checkHooks:a,checkLedger:u,renderDoctorReport:m,doctorExitCode:l}=await import("./doctor.js"),g=[e(),t(y),await s(x),await n(x,y),o(F()||P),await c(x,y,F()||P),a(r(process.cwd())),u(await lt(),sn())];console.log(m(g)),process.exit(l(g))}if(process.argv[2]==="cls-ingest"){try{const e=process.argv[3];(!e||!y)&&process.exit(0);let t;try{t=JSON.parse(e)}catch{process.exit(0)}const s=t.instance_id??P;(!s||!t.source)&&process.exit(0),await z("cls_ingest",{instance_id:s,source:t.source,payload:t.payload??{}})}catch{}process.exit(0)}if(!y){const e=Dt();if(e)try{const t=await fetch(Jt(e),{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:Ut(e),signal:AbortSignal.timeout(8e3)});if(t.ok){const s=await t.json();s.access_token&&(y=s.access_token,le(s.access_token),S("m2m_auth_completed",{grant:"client_credentials",client_id:e.clientId}),process.stderr.write(`\u{1F916} cachly: authenticated via client_credentials (M2M, headless).
342
+ Last entries:`);for(const n of s){const o=n.prevented>0?`+${n.prevented} prevented`:`-${n.injected} injected`;console.log(` \u2022 ${n.ts.slice(0,19)} ${n.event}: ${o}${n.note?` (${n.note})`:""}`)}}console.log(""),process.exit(0)}if(process.argv[2]==="uninstall"){const{homedir:e,tmpdir:t}=await import("node:os"),{resolve:s}=await import("node:path"),{createInterface:n}=await import("node:readline/promises"),o=process.argv.slice(3),r={projekt:s((a=>{const u=o.indexOf(`--${a}`);return u!==-1?o[u+1]:void 0})("project-dir")??"."),heim:process.env.HOME??process.env.USERPROFILE??process.env.APPDATA??e(),tmp:t(),schluessel:oe(),instanz:F(),apiUrl:x,istTty:process.stdin.isTTY===!0&&process.stdout.isTTY===!0,ausgabe:a=>console.log(a),frage:async a=>{const u=n({input:process.stdin,output:process.stdout});try{return/^(y|yes|j|ja)$/i.test((await u.question(a)).trim())}finally{u.close()}}};process.exit(await Jo(o,r))}if(process.argv[2]==="doctor"){const{checkNodeVersion:e,checkCredential:t,checkApiReachable:s,checkAuthAccepted:n,checkInstance:o,checkVectorCoverage:c,inspectAmbientHooks:r,checkHooks:a,checkLedger:u,renderDoctorReport:m,doctorExitCode:l}=await import("./doctor.js"),g=[e(),t(y),await s(x),await n(x,y),o(F()||N),await c(x,y,F()||N),a(r(process.cwd())),u(await lt(),sn())];console.log(m(g)),process.exit(l(g))}if(process.argv[2]==="cls-ingest"){try{const e=process.argv[3];(!e||!y)&&process.exit(0);let t;try{t=JSON.parse(e)}catch{process.exit(0)}const s=t.instance_id??N;(!s||!t.source)&&process.exit(0),await z("cls_ingest",{instance_id:s,source:t.source,payload:t.payload??{}})}catch{}process.exit(0)}if(!y){const e=Dt();if(e)try{const t=await fetch(Jt(e),{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:Ut(e),signal:AbortSignal.timeout(8e3)});if(t.ok){const s=await t.json();s.access_token&&(y=s.access_token,le(s.access_token),S("m2m_auth_completed",{grant:"client_credentials",client_id:e.clientId}),process.stderr.write(`\u{1F916} cachly: authenticated via client_credentials (M2M, headless).
343
343
  `))}else process.stderr.write(`\u26A0\uFE0F cachly: client_credentials auth failed (${t.status}). Check CACHLY_CLIENT_ID / CACHLY_CLIENT_SECRET.
344
344
  `),S("m2m_auth_failed",{status:t.status})}catch(t){process.stderr.write(`\u26A0\uFE0F cachly: client_credentials auth error: ${t.message}
345
345
  `),S("m2m_auth_failed",{reason:"network"})}}const hs=["demo","share","publish","health","autosetup","setup","autopilot","init","digest","invite","badge","join","upgrade","bench","tool-specs","openapi","ambient-credit","ambient-stats","doctor","uninstall"];if(!y&&!hs.includes(process.argv[2]??""))if(!process.argv[2]&&process.stdout.isTTY===!0&&Gt){const n=`
@@ -362,7 +362,7 @@ Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
362
362
  \u{1F9E0} cachly: no API key yet \u2014 the first cachly tool call creates a test Brain on EU servers, no sign-up.
363
363
  (Own account: npx @cachly-dev/mcp-server@latest autopilot)
364
364
 
365
- `);else{const e=Nt(y);if(e!==null){const t=Math.floor((e-Date.now())/6e4);t<=0?process.stderr.write(`
365
+ `);else{const e=Pt(y);if(e!==null){const t=Math.floor((e-Date.now())/6e4);t<=0?process.stderr.write(`
366
366
  \u26A0\uFE0F cachly: CACHLY_JWT expired ${Math.abs(t)} minute(s) ago.
367
367
  All tool calls will fail. Get a fresh token at ${j("/setup-ai","jwt-expiry")}
368
368
 
package/glama.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://glama.ai/mcp/schemas/server.json",
3
- "version": "0.10.204",
3
+ "version": "0.10.205",
4
4
  "maintainers": [
5
5
  "HeinrichNebula"
6
6
  ],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cachly-dev/mcp-server",
3
- "version": "0.10.204",
3
+ "version": "0.10.205",
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.204",
9
+ "version": "0.10.205",
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.204",
15
+ "version": "0.10.205",
16
16
  "transport": {
17
17
  "type": "stdio"
18
18
  }