@cachly-dev/mcp-server 0.10.205 → 0.10.207
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/ambient-hook.js +3 -3
- package/dist/src/ambient-ledger.js +5 -5
- package/dist/src/brain-watch-hook.js +4 -7
- package/dist/src/handlers/fedbrain.js +35 -35
- package/dist/src/index.js +46 -45
- package/dist/src/tools.js +1 -1
- package/glama.json +1 -1
- package/hooks/cachly-ambient-einblendung.mjs +2 -2
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/src/index.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
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.
|
|
2
|
+
import{setzeClientKennung as Ot}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 zt}from"./auth.js";import{cachlyUrl as j}from"./cachly-url.js";import{nutzungsSchluessel as Jt}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 ze}from"./notifier.js";import{fileURLToPath as Je}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]===Je(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 Bs=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 O=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 En({wurzeln:e,env:process.env,cwd:process.cwd(),dateiPfad:Je})}function re(){return Ze?gt(process.env):!1}function Ce(e,t,s){!e||!re()||Sn({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=>Oe("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()&&In()}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()&&wn({})&&Date.now()<t;)await new Promise(o=>setTimeout(o,yn));const s=Le();if(!s)return!1;y=s,le(s);const n=ut();n&&!O&&(O=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=bn();t&&(Ne(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(O)return O;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 O=o.id,Z=0,O;const c=await io();if(c)return O=c,Z=0,Ne(c,re(),Te()),pe(c),Ce(c),O}}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=Jo(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(),O&&pe(O),"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
|
|
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 _n(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
|
|
|
@@ -22,7 +22,7 @@ Complete your checkout at: ${j("/instances","upgrade")}`:r=`Brain instance "${t.
|
|
|
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 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
|
|
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 No}from"./handlers/roadmap.js";import{handleAdvancedTool as Oo}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 zo}from"./uninstall.js";import{gitLesen as rt}from"./git-ohne-shell.js";import{browserAdresse as Jo,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,teileNachInstanz as an}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 cn,waehleTestSchluessel as ln,starteKeycloakAnmeldung as dn,warteAufKeycloakAnmeldung as un,uebernimm as pn,brainImKonto as mn,erfolgsText as gn,fehlerText as fn,ersetzeSchluessel as hn}from"./uebernahme.js";import{WARTE_TAKT_MS as yn,auftragLiegt as mt,nimmAuftrag as bn,sichereKonto as vn,sperreLiegt as wn,startwissenEingeschaltet as gt}from"./konto-anlegen.js";import{sichereZugang as xn,echterWert as xe}from"./zugang.js";import{zeitpunkt as W}from"./zeitmessung.js";import{warteAufLaufendeInstanz as _n,gemeinsamerAufbau as $n}from"./instanz-warten.js";import{merkeNeuesBrain as Ne,startetLautLetztemBlick as kn}from"./leeres-brain.js";import{starteStartwissen as Sn,startwissenGestartet as An,beanspruchStartwissen as Cn,holeStartwissenHinweis as Tn,waehleProjektOrdner as En,startvorratErlaubt as In}from"./startwissen.js";import{eigeneFassung as Rn,pruefeNeueFassung as jn,holeNeueFassungHinweis as Bn}from"./neue-fassung.js";import{beiStdinEnde as Ln}from"./stdin-ende.js";import{merkeWerkzeugAufruf as Nn,starteBrandWachhund as On}from"./brand-wachhund.js";import{sichtbareWerkzeuge as Pn,VERTEILER as ft}from"./werkzeug-auswahl.js";import{buildLessonsMarkdown as Hn,buildLessonsJsonl as Mn,vonRohLektion as Dn}from"./brain-export.js";import{detectEditor as Un}from"./editor.js";import{milestoneSent as ht,markMilestoneSent as yt}from"./funnel-milestones.js";import{kostprobeUebrig as zn,kostprobeVerbrauchen as Jn,kostprobeHinweis as Fn,schrankeNachKostproben as Wn}from"./kostprobe.js";import{netBalance as Yn}from"./ambient-recall.js";import{handleShareTool as Oe}from"./handlers/share.js";import{handleVizTool as Kn}from"./handlers/viz.js";import{commitArt as qn,istRueckbau as Gn,zaehleLektionen as Vn}from"./commit-art.js";import{TOOLS as ge}from"./tools.js";let bt=!1,_e=!1;function vt(){return Un()}function Zn(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 Qn(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?Qn(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 Xn(e,t){return rn({apiUrl:x,jwt:y,instanceId:e},t)}async function es(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 ts=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"]),os={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 ns(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 ss(e,t){if(!ts.has(e)||!t)return null;const{isFree:s}=await ns(t);if(!s)return null;const n=os[e]??"A Premium intelligence feature.";if(zn(e)){const o=Jn(e);return{kostprobe:Fn(e,o,wt)}}return{sperre:Wn(e,n,wt)}}async function is(e,t){try{await(await H(e)).hincrby(Jt(e),t,1)}catch{}}async function rs(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 as(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}
|
|
@@ -30,10 +30,10 @@ cachly: code ${t.userCode}
|
|
|
30
30
|
|
|
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
|
-
`)}async function
|
|
34
|
-
`)}return
|
|
33
|
+
`)}async function cs(e){if(!e)return!0;if(An(e))return!1;try{return await Cn(await H(e),"sitzungsstart")}catch{return!0}}async function J(e,t){if(!y&&await Ee(eo))return J(e,t);if(!y){if(es(e),G){const i=await Xe(G);return i==="done"?J(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 xn({schluessel:y,konfigurierteInstanz:O,aufrufInstanz:t.instance_id,werkzeugName:e,holeSofortTest:async()=>{W("sofort-test: Anfang");const i=await vn({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&&Ne(d.instanzId,re(),Te()),d},ablagen:{setzeSchluessel:i=>{y=i},setEmbedJwt:le,saveApiKey:i=>Q(i),persistApiKeyToConfig:ue,merkeInstanz:i=>{O=i,Z=0},persistInstanceIdToConfig:pe},meldeEreignis:S,werkzeug:()=>J(e,t),anmelden:()=>as(e),neuesBrain:Ce})}if(!t.instance_id){const i=await Qe();i&&(t={...t,instance_id:i})}const s=await ss(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&&is(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&&rs(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??O??""})));const i=t.instance_id??O??"",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(!kn(i)){if(!T&&h.length>100)S("recall_best_solution",d);else if(T&&t.workspace_path&&await cs(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 N=await Oe("brain_seed_starter",{instance_id:i},H,P);N&&(S("brain_seed_starter",{...d,auto:!0},{seeded_count:16,auto:!0}),C=`
|
|
35
35
|
---
|
|
36
|
-
`+String(
|
|
36
|
+
`+String(N))}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+`
|
|
38
38
|
---
|
|
39
39
|
`+I+C}}catch(E){return S("brain_from_git_failed",{...d,reason:E instanceof Error?E.message.slice(0,120):"unknown"}),String(o)+`
|
|
@@ -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,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??
|
|
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,
|
|
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??O??""}))),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 No(e,t,H,P);if(l!==null)return l;const g=await Oo(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??O??"";S("brain_predict",y?{api_key:y,instance_id:i}:{instance_id:i})}return u(w)}const v=await Oe(e,t,H,P);if(v!==null)return v;const b=await Kn(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??O??"",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
|
+
`);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,N=k?k<new Date:!1;d=["\u2705 JWT decoded",` Sub (user ID): ${C}`,` Provider: ${$}`,` Issuer: ${I}`,` Expires: ${k?k.toISOString():"never"} ${N?"\u26A0\uFE0F EXPIRED \u2013 get a new token!":"\u2705"}`].join(`
|
|
47
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===
|
|
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===O?" \u2190 active":"";if(C.push(` ${$} **${I.name}** (\`${I.id}\`) \xB7 ${I.status}${k}`),I.status==="running"&&I.host){const N=ne.get(I.id);if(N)try{await N.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,10 +60,10 @@ ${o}`}return o}const c=await Ro(e,t,H,P);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}=
|
|
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 ls(e){e.setRequestHandler(Ge,St),e.setRequestHandler(We,Rt),e.setRequestHandler(qe,At),e.setRequestHandler(Ke,Ct),e.setRequestHandler(Ye,Tt)}function ds(){const e=new Fe({name:"cachly-mcp",version:D},{capabilities:kt,instructions:$t});return ls(e),Et(e),e}function Et(e){const t=e.oninitialized;e.oninitialized=()=>{try{const s=e.getClientVersion();Ot(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 us(e){if(!fe){if(X){await X;return}X=(async()=>{fe=!0,Pe=e;try{await J("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 J("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 J("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)||O||xe(process.env.CACHLY_BRAIN_INSTANCE_ID);o&&await us(o).catch(()=>{})}else X&&await X.catch(()=>{});n.has(t)||It++;try{Nn(),W(`werkzeug ${t}: Anfang`);const o=await J(t,s??{});return W(`werkzeug ${t}: Antwort fertig`),{content:[{type:"text",text:on(t,o)+Tn()+Bn(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 ze("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
|
-
`)}),process.stdout.on("error",()=>{}),process.stdin.on("error",()=>{});function
|
|
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
|
|
65
|
+
`)}),process.stdout.on("error",()=>{}),process.stdin.on("error",()=>{});function ps(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 ms(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){cn(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 ms(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
|
+
`)}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 gs(e){return`${st}
|
|
67
67
|
## Cachly AI Brain \u2014 Always Active
|
|
68
68
|
|
|
69
69
|
The Brain MCP server runs automatically. Instance: \`${e}\`
|
|
@@ -118,7 +118,7 @@ Report predicted failure risks to the user before proceeding.
|
|
|
118
118
|
|
|
119
119
|
### Half-finished code rule:
|
|
120
120
|
Never commit code that does not compile. Run \`tsc --noEmit\` / \`go build ./...\` before every commit.
|
|
121
|
-
${it}`}async function
|
|
121
|
+
${it}`}async function Nt(e,t){const{existsSync:s}=await import("node:fs"),{resolve:n}=await import("node:path"),o=Do.filter(a=>!a.nurMitIdea||s(n(e,".idea"))).map(a=>({path:n(e,...a.pfad),prefix:a.prefix})),c=gs(t),r={};for(const{path:a,prefix:u}of o)r[a]=await Uo(a,c,u);return r}if(process.argv[2]==="digest"){const e=oe(),t=F();(!e||!t)&&(console.log(`
|
|
122
122
|
\u26A0\uFE0F No cachly key or Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot
|
|
123
123
|
`),process.exit(1)),process.stdout.write(`
|
|
124
124
|
\u{1F9E0} Fetching your weekly Brain digest...
|
|
@@ -134,8 +134,8 @@ ${it}`}async function Ot(e,t){const{existsSync:s}=await import("node:fs"),{resol
|
|
|
134
134
|
`),process.exit(1)),process.stdout.write(`
|
|
135
135
|
\u{1F4E4} Exporting your Brain...
|
|
136
136
|
|
|
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(
|
|
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,
|
|
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(Dn).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,Hn(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,Mn(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
|
|
@@ -165,12 +165,12 @@ Try it free: ${n}
|
|
|
165
165
|
`),process.exit(0));let d=y;if(!d){console.log(`
|
|
166
166
|
No API key found \u2014 starting sign-in (10 seconds)...
|
|
167
167
|
`);try{const A=await fetch(`${x}/api/v1/auth/device/code`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({client_id:"cachly-mcp-cli"}),signal:AbortSignal.timeout(1e4)});if(A.ok){const C=await A.json();console.log(` \u{1F449} Open: \x1B[36m${C.verification_uri}\x1B[0m`),console.log(` Code: \x1B[1m${C.user_code}\x1B[0m
|
|
168
|
-
`);const I=(C.interval??5)*1e3;for(let $=0;$<24;$++){await new Promise(k=>setTimeout(k,I));try{const k=await fetch(`${x}/api/v1/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:C.device_code,client_id:"cachly-mcp-cli"}),signal:AbortSignal.timeout(8e3)});if(k.ok){const
|
|
168
|
+
`);const I=(C.interval??5)*1e3;for(let $=0;$<24;$++){await new Promise(k=>setTimeout(k,I));try{const k=await fetch(`${x}/api/v1/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:C.device_code,client_id:"cachly-mcp-cli"}),signal:AbortSignal.timeout(8e3)});if(k.ok){const N=await k.json();if(N.access_token){d=N.access_token;break}}}catch{}}d||(console.log(`
|
|
169
169
|
\u274C Sign-in timed out. Run the command again.
|
|
170
170
|
`),process.exit(1)),console.log(` \u2705 Signed in!
|
|
171
171
|
`)}}catch(A){console.log(`
|
|
172
172
|
\u26A0\uFE0F Could not start sign-in: ${A.message}`),console.log(` Set CACHLY_JWT manually from ${j("/setup-ai","join")}
|
|
173
|
-
`),process.exit(1)}}d&&d!==y&&Q(d);const h=process.cwd(),T=r(),L=[{label:".mcp.json (Claude Code project)",path:o(h,".mcp.json")},{label:".cursor/mcp.json",path:o(h,".cursor","mcp.json")},{label:".windsurf/mcp.json",path:o(h,".windsurf","mcp.json")},{label:".vscode/mcp.json (Copilot/Cline)",path:o(h,".vscode","mcp.json")},{label:"~/.claude/mcp.json (global)",path:o(T,".claude","mcp.json"),global:!0}];let E=0;for(const{label:A,path:C,global:I}of L){const $=c(C);if(!(!I&&!n($)&&!n(C)))try{await s($,{recursive:!0});let k={};if(n(C))try{k=JSON.parse(await t(C,"utf-8"))}catch{try{await(await import("node:fs/promises")).rename(C,C+".bak")}catch{}}const
|
|
173
|
+
`),process.exit(1)}}d&&d!==y&&Q(d);const h=process.cwd(),T=r(),L=[{label:".mcp.json (Claude Code project)",path:o(h,".mcp.json")},{label:".cursor/mcp.json",path:o(h,".cursor","mcp.json")},{label:".windsurf/mcp.json",path:o(h,".windsurf","mcp.json")},{label:".vscode/mcp.json (Copilot/Cline)",path:o(h,".vscode","mcp.json")},{label:"~/.claude/mcp.json (global)",path:o(T,".claude","mcp.json"),global:!0}];let E=0;for(const{label:A,path:C,global:I}of L){const $=c(C);if(!(!I&&!n($)&&!n(C)))try{await s($,{recursive:!0});let k={};if(n(C))try{k=JSON.parse(await t(C,"utf-8"))}catch{try{await(await import("node:fs/promises")).rename(C,C+".bak")}catch{}}const N=k.mcpServers??{},Y=N.cachly??{},K=Y.env??{};K.CACHLY_BRAIN_INSTANCE_ID=l,d&&I&&!K.CACHLY_JWT&&(K.CACHLY_JWT=d),x!==jt&&(K.CACHLY_API_URL=x),N.cachly={...Y,command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:K},k.mcpServers=N,await e(C,JSON.stringify(k,null,2),"utf-8"),console.log(` \u2705 ${A}`),E++}catch(k){k.code!=="ENOENT"&&console.log(` \u26A0\uFE0F ${A}: ${k.message}`)}}console.log(""),E===0?console.log(" \u26A0\uFE0F No editor configs found \u2014 run `cachly setup` first.\n"):(console.log(` \u{1F9E0} You're now sharing Brain: \x1B[1m${g}\x1B[0m`),console.log(` Restart your editor \u2014 your AI arrives pre-briefed from the team Brain.
|
|
174
174
|
`),console.log(" \u{1F4DB} Add the badge to your README:"),console.log(` npx @cachly-dev/mcp-server@latest badge
|
|
175
175
|
`)),process.exit(0)}if(process.argv[2]==="upgrade"){process.stdout.write(`
|
|
176
176
|
\u23F3 Checking for updates...
|
|
@@ -186,8 +186,8 @@ Try it free: ${n}
|
|
|
186
186
|
`),console.log(` Example: cd ~/my-project && npx @cachly-dev/mcp-server@latest demo
|
|
187
187
|
`),process.exit(0));let c="";try{c=rt(o,["config","user.name"]).trim().split(" ")[0]??""}catch{}let r=n(o);try{const $=JSON.parse(t(s(o,"package.json"),"utf-8"));$.name&&(r=$.name.replace(/^@[^/]+\//,""))}catch{}let a="";try{a=rt(o,["log","HEAD","--pretty=format:%H|||%s|||%ad|||%an","--date=short","--no-merges","-n","200"],{timeoutMs:3e4})}catch{console.log(`\u26A0\uFE0F Could not read git log. Make sure you have commits.
|
|
188
188
|
`),process.exit(0)}const u=a.trim().split(`
|
|
189
|
-
`).filter(Boolean).map($=>{const[k,
|
|
190
|
-
`),process.exit(0));const m=new Map,l=[],g=[],w=[],v=new Set;let b=0;for(const $ of u){const k=
|
|
189
|
+
`).filter(Boolean).map($=>{const[k,N,Y,K]=$.split("|||");return{sha:(k??"").trim().slice(0,8),subject:(N??"").trim(),date:(Y??"").trim(),author:(K??"").trim()}});u.length===0&&(console.log(`\u26A0\uFE0F No commits found.
|
|
190
|
+
`),process.exit(0));const m=new Map,l=[],g=[],w=[],v=new Set;let b=0;for(const $ of u){const k=qn($.subject);m.set(k,(m.get(k)??0)+1),Gn($.subject)&&b++,k==="fix"&&l.length<5&&l.push($.subject.slice(0,72)),k==="feat"&&g.length<5&&g.push($.subject.slice(0,72)),k==="security"&&w.length<3&&w.push($.subject.slice(0,72)),$.author&&v.add($.author)}const p=Vn(u.map($=>$.subject)),i=`${u[u.length-1]?.date??"?"} \u2192 ${u[0]?.date??"?"}`,d=p>=501?"Oracle":p>=201?"Architect":p>=51?"Expert":p>=11?"Explorer":"Apprentice",T=`${c?`Hey ${c} \u2014 `:""}here's what your AI would know about ${r}`;process.stdout.write("\x1B[2K\r"),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log(`\u2502 \x1B[1m\u{1F9E0} ${T.slice(0,58).padEnd(58)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Commits analysed : \x1B[33m${String(u.length).padEnd(6)}\x1B[0m Date range: \x1B[90m${i.slice(0,23).padEnd(23)}\x1B[0m \u2502`),console.log(`\u2502 Lessons extracted: \x1B[32m${String(p).padEnd(6)}\x1B[0m Contributors: \x1B[36m${String(v.size).padEnd(20)}\x1B[0m\u2502`),console.log(`\u2502 Brain Level : \x1B[35m${d.padEnd(10)}\x1B[0m Reverts: \x1B[33m${String(b).padEnd(21)}\x1B[0m\u2502`),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");const L=[...m.entries()].filter(([$])=>$!=="chore").sort(($,k)=>k[1]-$[1]),E=($,k)=>"\u2588".repeat(Math.round($/k*20)).padEnd(20),A=Math.max(...L.map(([,$])=>$),1);console.log("\u2502 \x1B[90mCategory breakdown:\x1B[0m \u2502");for(const[$,k]of L){const N={fix:"\u{1F527}",feat:"\u2728",perf:"\u26A1",security:"\u{1F512}",deploy:"\u{1F680}",refactor:"\u{1F504}"}[$]??"\u2022";console.log(`\u2502 ${N} \x1B[36m${$.padEnd(10)}\x1B[0m \x1B[35m${E(k,A)}\x1B[0m \x1B[33m${String(k).padStart(3)}\x1B[0m \u2502`)}if(w.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[31m\u{1F512} Security fixes your AI would know:\x1B[0m \u2502");for(const $ of w)console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}if(l.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[33m\u{1F527} Bug fixes your AI would never repeat:\x1B[0m \u2502");for(const $ of l.slice(0,4))console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}if(g.length>0){console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[32m\u2728 Features & decisions it would recall:\x1B[0m \u2502");for(const $ of g.slice(0,3))console.log(`\u2502 \x1B[90m\u2022 ${$.slice(0,58).padEnd(58)}\x1B[0m \u2502`)}console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 \x1B[32m\u{1F4A1} With cachly, your AI arrives pre-briefed every session.\x1B[0m \u2502"),console.log("\u2502 \x1B[32m No more re-explaining. No more repeated mistakes.\x1B[0m \u2502"),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),console.log("");const C=new URLSearchParams({repo:r,commits:String(u.length),lessons:String(p),level:d,authors:String(v.size),reverts:String(b)}),I=j(`/preview?${C.toString()}`,"demo");console.log(" \x1B[1mMake this permanent (free, 1\u20135 minutes):\x1B[0m"),console.log(" \x1B[32m$ npx @cachly-dev/mcp-server@latest autopilot\x1B[0m"),console.log(""),console.log(` \x1B[90m\u{1F517} Shareable preview:\x1B[0m \x1B[36m${I}\x1B[0m`),console.log(""),console.log(" Works with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 Copilot \xB7 Cline \xB7 Zed"),console.log(" GDPR \xB7 German servers \xB7 free tier, no credit card"),console.log(""),process.exit(0)}if(process.argv[2]==="share"){const e=oe(),t=F();(!e||!t)&&(console.log(`
|
|
191
191
|
\u26A0\uFE0F No cachly key or Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot (takes 1\u20135 minutes)
|
|
192
192
|
`),process.exit(1)),process.stdout.write(`
|
|
193
193
|
\u{1F9E0} Fetching your Brain stats...
|
|
@@ -215,14 +215,14 @@ ${l}
|
|
|
215
215
|
`),process.exit(1)),process.stdout.write(e(ge,t,D)+`
|
|
216
216
|
`,()=>process.exit(0))}if(process.argv[2]==="badge"){const e=F();e||(console.log(`
|
|
217
217
|
\u26A0\uFE0F No Brain instance found (environment or ~/.cachly/credentials.json).`),console.log(` Run: npx @cachly-dev/mcp-server@latest autopilot (takes 1\u20135 minutes)
|
|
218
|
-
`),process.exit(1));const t=`${x}/api/v1/badge/${e}`,s=j("/","badge"),n=`[](${s})`,o=`<a href="${s}"><img src="${t}" alt="cachly Brain" /></a>`;console.log(""),console.log("\x1B[35m \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\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly Brain Badge\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \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\u2550\u255D\x1B[0m"),console.log(""),console.log(" Paste into your README.md:"),console.log(""),console.log(` \x1B[32m${n}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Or paste into HTML:"),console.log(""),console.log(` \x1B[36m${o}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Badge URL (live, updates every hour):"),console.log(` \x1B[90m${t}\x1B[0m`),console.log(""),console.log(" \x1B[2mThe badge shows your current lesson count \u2014 no auth required,"),console.log(" safe to embed in public repos. Updates hourly.\x1B[0m"),console.log(""),process.exit(0)}if(!process.argv[2]&&process.stdout.isTTY){console.log(""),console.log("\x1B[35m \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\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly \u2014 Persistent AI Memory for Developers\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \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\u2550\u255D\x1B[0m"),console.log(""),console.log(" Stop re-teaching your AI every morning."),console.log(" cachly gives it a permanent brain \u2014 pre-briefed every session."),console.log("");const e=(t,s)=>console.log(` \x1B[36m ${t.padEnd(22)}\x1B[0m ${s}`);console.log(" \x1B[1mStart:\x1B[0m \x1B[1m\x1B[32mnpx @cachly-dev/mcp-server@latest autopilot\x1B[0m \u2190 \x1B[1mOne command, fully ready\x1B[0m"),console.log(" Every command below runs as: npx @cachly-dev/mcp-server@latest <command>"),console.log(""),console.log(" \x1B[1mEvery day:\x1B[0m"),e("status","Lessons, recalls and team at a glance"),e("ambient-stats","Tokens injected vs saved \u2014 the honest net, even when negative"),e("doctor","Diagnose a broken or missing install"),e("health","Check key, API, editor configs and git hook"),e("digest","What your Brain learned this week"),console.log(" \x1B[1mSet up:\x1B[0m"),e("demo","Try it first (no account)"),e("setup","Interactive setup (pick editors)"),e("init","Write the config for one editor (flags)"),e("claim","Keep a test Brain in your own account"),e("upgrade","Check for updates"),e("uninstall","Take cachly out of this project (--dry-run first)"),console.log(" \x1B[1mYour data:\x1B[0m"),e("export","Write your lessons to disk (md / jsonl)"),e("index [dir]","Index a project into the Brain (CI)"),e("learn-git [repo]","Learn lessons from recent commits (CI)"),console.log(" \x1B[1mTeam & sharing:\x1B[0m"),e("invite","Invite a teammate"),e("join <token>","Accept a Brain invite"),e("share","Share your Brain stats"),e("publish","Publish an importable Brain snapshot"),e("badge","README badge for your Brain"),console.log(" \x1B[1mMore:\x1B[0m"),e("bench","Recall quality vs flat-file memory"),e("tool-specs | openapi","Tool definitions for other agent frameworks"),console.log(""),console.log(" \x1B[90mWorks with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 GitHub Copilot \xB7 Cline \xB7 Zed\x1B[0m"),console.log(` \x1B[90mGDPR \xB7 German servers \xB7 ${ge.length} MCP tools\x1B[0m`),console.log(""),process.exit(0)}const
|
|
218
|
+
`),process.exit(1));const t=`${x}/api/v1/badge/${e}`,s=j("/","badge"),n=`[](${s})`,o=`<a href="${s}"><img src="${t}" alt="cachly Brain" /></a>`;console.log(""),console.log("\x1B[35m \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\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly Brain Badge\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \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\u2550\u255D\x1B[0m"),console.log(""),console.log(" Paste into your README.md:"),console.log(""),console.log(` \x1B[32m${n}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Or paste into HTML:"),console.log(""),console.log(` \x1B[36m${o}\x1B[0m`),console.log(""),console.log(" \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),console.log(" Badge URL (live, updates every hour):"),console.log(` \x1B[90m${t}\x1B[0m`),console.log(""),console.log(" \x1B[2mThe badge shows your current lesson count \u2014 no auth required,"),console.log(" safe to embed in public repos. Updates hourly.\x1B[0m"),console.log(""),process.exit(0)}if(!process.argv[2]&&process.stdout.isTTY){console.log(""),console.log("\x1B[35m \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\u2550\u2557\x1B[0m"),console.log("\x1B[35m \u2551\x1B[0m \x1B[1m\u{1F9E0} cachly \u2014 Persistent AI Memory for Developers\x1B[0m \x1B[35m\u2551\x1B[0m"),console.log("\x1B[35m \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\u2550\u255D\x1B[0m"),console.log(""),console.log(" Stop re-teaching your AI every morning."),console.log(" cachly gives it a permanent brain \u2014 pre-briefed every session."),console.log("");const e=(t,s)=>console.log(` \x1B[36m ${t.padEnd(22)}\x1B[0m ${s}`);console.log(" \x1B[1mStart:\x1B[0m \x1B[1m\x1B[32mnpx @cachly-dev/mcp-server@latest autopilot\x1B[0m \u2190 \x1B[1mOne command, fully ready\x1B[0m"),console.log(" Every command below runs as: npx @cachly-dev/mcp-server@latest <command>"),console.log(""),console.log(" \x1B[1mEvery day:\x1B[0m"),e("status","Lessons, recalls and team at a glance"),e("ambient-stats","Tokens injected vs saved \u2014 the honest net, even when negative"),e("doctor","Diagnose a broken or missing install"),e("health","Check key, API, editor configs and git hook"),e("digest","What your Brain learned this week"),console.log(" \x1B[1mSet up:\x1B[0m"),e("demo","Try it first (no account)"),e("setup","Interactive setup (pick editors)"),e("init","Write the config for one editor (flags)"),e("claim","Keep a test Brain in your own account"),e("upgrade","Check for updates"),e("uninstall","Take cachly out of this project (--dry-run first)"),console.log(" \x1B[1mYour data:\x1B[0m"),e("export","Write your lessons to disk (md / jsonl)"),e("index [dir]","Index a project into the Brain (CI)"),e("learn-git [repo]","Learn lessons from recent commits (CI)"),console.log(" \x1B[1mTeam & sharing:\x1B[0m"),e("invite","Invite a teammate"),e("join <token>","Accept a Brain invite"),e("share","Share your Brain stats"),e("publish","Publish an importable Brain snapshot"),e("badge","README badge for your Brain"),console.log(" \x1B[1mMore:\x1B[0m"),e("bench","Recall quality vs flat-file memory"),e("tool-specs | openapi","Tool definitions for other agent frameworks"),console.log(""),console.log(" \x1B[90mWorks with: Claude Code \xB7 Cursor \xB7 Windsurf \xB7 GitHub Copilot \xB7 Cline \xB7 Zed\x1B[0m"),console.log(` \x1B[90mGDPR \xB7 German servers \xB7 ${ge.length} MCP tools\x1B[0m`),console.log(""),process.exit(0)}const fs={cursor:{datei:".cursor/hooks.json",name:"Cursor",wie:"session briefing, per-prompt recall after the first tool call"},copilot:{datei:Go,name:"VS Code / Copilot",wie:"session briefing, per-prompt recall"},codex:{datei:Vo,name:"Codex",wie:"session briefing, per-prompt recall; trust it once in /hooks"},gemini:{datei:Zo,name:"Gemini CLI",wie:"session briefing, per-prompt recall"}};function hs(e,t,s){if(!t)return;const{datei:n,name:o,wie:c}=fs[e];if(t.hooks==="skipped"){console.log(`\u26A0\uFE0F ${s}${n} ${t.grund??"is not valid JSON"} \u2014 left untouched, ${o} hooks not wired`);return}const r=t.hooks==="unchanged"?"\u2713 ":"\u2705 ",a=t.hooks==="written"?"Written":t.hooks==="merged"?"Merged":"Already wired";console.log(`${r}${s}${a}: ${n} (Ambient Recall for ${o} \u2014 ${c})`)}async function ye(e,t,s,n){const o={cursor:Wo,copilot:Yo,codex:Ko,gemini:qo}[e];hs(e,await o(t,s).catch(()=>null),n)}if(process.argv[2]==="init"){const e=Date.now(),{writeFile:t,mkdir:s,readFile:n}=await import("node:fs/promises"),{resolve:o,dirname:c}=await import("node:path"),r=process.argv.slice(3),a=i=>{const d=r.indexOf(`--${i}`);return d!==-1?r[d+1]:void 0};let u=a("instance-id")??process.env.CACHLY_BRAIN_INSTANCE_ID,m=a("api-key")??process.env.CACHLY_JWT;const l=(a("editor")??"claude").toLowerCase(),g=o(a("project-dir")??"."),w=a("api-url");if(w&&(x=w.replace(/\/+$/,"")),!u||!m)try{const{existsSync:i}=await import("node:fs"),d=process.env.HOME??process.env.USERPROFILE??"",h=d?o(d,".claude","mcp.json"):"";if(h&&i(h)){const L=JSON.parse(await n(h,"utf-8")).mcpServers?.cachly?.env??{};m??=L.CACHLY_JWT,u??=L.CACHLY_BRAIN_INSTANCE_ID,m&&u&&console.log("\u2713 Reusing credentials from ~/.claude/mcp.json (saved by a prior setup)")}}catch{}(!u||!m)&&(console.error(`
|
|
219
219
|
Usage: npx @cachly-dev/mcp-server@latest init --instance-id <uuid> --api-key <cky_live_...> [--editor claude|cursor|windsurf|copilot|continue|codex|gemini] [--project-dir /path] [--api-url https://your-self-hosted-backend]
|
|
220
220
|
`),console.error(`First time? Run the zero-config wizard (signs you in, auto-provisions): npx @cachly-dev/mcp-server@latest autopilot
|
|
221
221
|
`),console.error(`Get your credentials from: ${j("/setup-ai","init")}
|
|
222
|
-
`),process.exit(1));const v=
|
|
222
|
+
`),process.exit(1));const v=ps(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
|
|
225
|
+
\u2713 Already configured: ${i} (no change)`)}const b=await Nt(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(`
|
|
@@ -244,20 +244,20 @@ ${"\u2500".repeat(40)}`),c===0?console.log(`\u2705 All checks passed (${o} ok)
|
|
|
244
244
|
`),process.exit(1)),process.exit(0)}if(process.argv[2]==="claim"){const{readFile:e,writeFile:t}=await import("node:fs/promises"),{existsSync:s}=await import("node:fs"),{resolve:n}=await import("node:path"),{homedir:o}=await import("node:os"),c=i=>{const d=process.argv.indexOf(`--${i}`);return d!==-1?process.argv[d+1]:void 0};x=(c("api-url")??"https://api.cachly.dev").replace(/\/+$/,"");const r=(c("auth-url")??pt).replace(/\/+$/,"");console.log(`
|
|
245
245
|
\u{1F9E0} cachly \u2014 keep your test Brain in your own account
|
|
246
246
|
`),(x!=="https://api.cachly.dev"||r!==pt)&&console.log(`\u26A0\uFE0F Not the cachly servers: API ${x}, sign-in ${r}
|
|
247
|
-
`);const a=
|
|
247
|
+
`);const a=ln({argument:c("key"),credentials:Le()});a||(console.log("No test key (cky_trial_\u2026) was found in ~/.cachly/credentials.json."),console.log("If you already use your own cachly account, there is nothing to claim."),console.log(`Otherwise pass the key: npx @cachly-dev/mcp-server@latest claim --key cky_trial_\u2026
|
|
248
248
|
`),process.exit(1));const u=a.schluessel,m={argument:"--key",credentials:"~/.cachly/credentials.json"}[a.quelle];console.log(`Test key: ${u.slice(0,14)}\u2026 (from ${m})
|
|
249
249
|
`);let l="";try{console.log(`Step 1: Sign in to your cachly account
|
|
250
|
-
`);const i=await
|
|
250
|
+
`);const i=await dn(fetch,r);console.log(` Code: \x1B[1;33m${i.userCode}\x1B[0m`),console.log(" Open this URL and confirm the code:"),console.log(`${i.adresse}
|
|
251
251
|
`),ce(i.adresse,(d,h)=>{d||console.log(`
|
|
252
|
-
\u2139\uFE0F No browser could be opened here (${h??"unknown"}) \u2014 please open the URL yourself.`)}),process.stdout.write(" Waiting for sign-in"),l=await
|
|
252
|
+
\u2139\uFE0F No browser could be opened here (${h??"unknown"}) \u2014 please open the URL yourself.`)}),process.stdout.write(" Waiting for sign-in"),l=await un(fetch,i,{basis:r,puls:()=>process.stdout.write(".")}),console.log(` \x1B[32m\u2713\x1B[0m
|
|
253
253
|
`)}catch(i){console.error(`
|
|
254
254
|
|
|
255
255
|
${i.message}. Nothing was changed.
|
|
256
|
-
`),process.exit(1)}process.stdout.write("Step 2: Moving the test Brain into your account (it restarts once, up to a minute)\u2026");let g;try{g=await
|
|
256
|
+
`),process.exit(1)}process.stdout.write("Step 2: Moving the test Brain into your account (it restarts once, up to a minute)\u2026");let g;try{g=await pn(fetch,x,l,u,"mcp",`cachly-mcp/${D}`),console.log(` \x1B[32m\u2713\x1B[0m
|
|
257
257
|
`)}catch(i){console.error(`
|
|
258
258
|
|
|
259
|
-
${
|
|
260
|
-
`),process.exit(1)}y=g.apiKey,Q(g.apiKey),dt(g.instanceId,{apiKey:g.apiKey}),await ue(g.apiKey),await pe(g.instanceId);const w=o(),v=new Set([...Object.values(me).map(i=>n(process.cwd(),i)),n(w,".claude.json"),n(w,".claude","mcp.json"),n(w,".cursor","mcp.json"),n(w,".codeium","windsurf","mcp_config.json")]);let b=0;for(const i of v)if(s(i))try{const d=
|
|
259
|
+
${fn(i)}
|
|
260
|
+
`),process.exit(1)}y=g.apiKey,Q(g.apiKey),dt(g.instanceId,{apiKey:g.apiKey}),await ue(g.apiKey),await pe(g.instanceId);const w=o(),v=new Set([...Object.values(me).map(i=>n(process.cwd(),i)),n(w,".claude.json"),n(w,".claude","mcp.json"),n(w,".cursor","mcp.json"),n(w,".codeium","windsurf","mcp_config.json")]);let b=0;for(const i of v)if(s(i))try{const d=hn(await e(i,"utf-8"),u,g.apiKey);d.ersetzt&&(await t(i,d.text,"utf-8"),b++)}catch{}const p=await mn(fetch,x,g.apiKey,g.instanceId);console.log(gn(g,p)),console.log(`
|
|
261
261
|
New key stored in ~/.cachly/credentials.json${b?` and in ${b} editor config file(s) that held the test key`:""}.`),console.log(`Restart your editor (or reload its MCP servers) so it uses the new key.
|
|
262
262
|
`),process.exit(0)}const $e=process.argv[2]==="autopilot";if(process.argv[2]==="autosetup"||process.argv[2]==="setup"||$e){const{writeFile:e,mkdir:t,readFile:s}=await import("node:fs/promises"),{existsSync:n}=await import("node:fs"),{resolve:o,dirname:c}=await import("node:path"),{createInterface:r}=await import("node:readline"),a=Date.now(),u=$e?"autopilot":"setup",m=process.argv.indexOf("--api-url");m!==-1&&process.argv[m+1]&&(x=process.argv[m+1].replace(/\/+$/,""),console.log(`\u2139\uFE0F Using self-hosted backend: ${x}
|
|
263
263
|
`)),S("setup_started");const l=process.stdin.isTTY===!0,g=$e||process.argv.includes("--yes")||process.argv.includes("-y")||!l;$e?console.log(`\u{1F916} Autopilot \u2014 one-command setup (auth \u2192 instance \u2192 configs \u2192 Brain), zero prompts.
|
|
@@ -266,7 +266,7 @@ New key stored in ~/.cachly/credentials.json${b?` and in ${b} editor config file
|
|
|
266
266
|
\u{1F9E0} cachly AI Brain \u2014 Setup`),console.log(`\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
267
267
|
`);let b=process.env.CACHLY_JWT??"";if(b)console.log(`\u2713 Using token from CACHLY_JWT env var
|
|
268
268
|
`);else{console.log(`Step 1: Sign in to cachly (free, no credit card)
|
|
269
|
-
`),S("setup_auth_started");let f="",_="",R="",U=5e3,
|
|
269
|
+
`),S("setup_auth_started");let f="",_="",R="",U=5e3,z=!1,ee="cachly";try{const q=await fetch(`${x}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({}),signal:AbortSignal.timeout(8e3)});if(q.ok){const B=await q.json();f=B.device_code,_=B.user_code;const M=B.verification_uri||j("/device",u);R=`${M}${M.includes("?")?"&":"?"}code=${encodeURIComponent(_)}`,U=(B.interval??5)*1e3,z=!!f}}catch{}if(!z)try{const B=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(B.ok){const M=await B.json();f=M.device_code,_=M.user_code,R=M.verification_uri_complete,U=(M.interval??5)*1e3,z=!0,ee="keycloak"}}catch{}if(z&&f){console.log(` Code: \x1B[1;33m${_}\x1B[0m`),console.log(" Open this URL and confirm the code:"),console.log(`${R}
|
|
270
270
|
`),ce(R,(B,M)=>{if(B){S("device_browser_opened",{stelle:"setup"});return}S("device_browser_failed",{reason:M??"unknown",stelle:"setup"}),console.log(` \u2139\uFE0F No browser could be opened here (${M??"unknown"}) \u2014 please open the URL yourself.
|
|
271
271
|
`)}),process.stdout.write(" Waiting for authorization");const q=Date.now()+600*1e3;for(;Date.now()<q;){await new Promise(B=>setTimeout(B,U)),process.stdout.write(".");try{let B=null;if(ee==="cachly")try{const M=await fetch(`${x}/auth/device/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:f}),signal:AbortSignal.timeout(8e3)});M.status<500&&(B=await M.json())}catch{}else{const M="https://auth.cachly.dev/realms/cachly/protocol/openid-connect";try{B=await(await fetch(`${M}/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=${f}`,signal:AbortSignal.timeout(8e3)})).json()}catch{}}if(B?.access_token){b=B.access_token,console.log(` \x1B[32m\u2713 Authorized!\x1B[0m
|
|
272
272
|
`),S("setup_auth_completed"),S("device_flow_completed");break}B?.error==="slow_down"?U=Math.min(U+2e3,15e3):B?.error&&B.error!=="authorization_pending"&&(S("device_flow_failed",{reason:B.error}),console.error(`
|
|
@@ -288,16 +288,16 @@ API key is required. Aborting.
|
|
|
288
288
|
Failed to fetch instances: ${_}`),_.includes("401")&&(console.error(`Token rejected. Get a valid token at ${j("/setup-ai",u)}
|
|
289
289
|
`),ce(j("/setup-ai",u))),w.close(),process.exit(1)}if(console.log(` found ${p.length}
|
|
290
290
|
`),p.length===0){process.stdout.write("\u23F3 Creating your free Brain instance...");try{const f=await fetch(`${x}/api/v1/instances/auto`,{method:"POST",headers:{Authorization:`Bearer ${b}`,"Content-Type":"application/json"}});if(!f.ok)throw new Error(`HTTP ${f.status}`);const _=await f.json();if(_.instance)p=[_.instance];else if(_.instance_id){const R=_.instance_id;console.log(` \u2713 created (${R.slice(0,8)}\u2026)
|
|
291
|
-
`),process.stdout.write("\u23F3 Waiting for instance to start");for(let U=0;U<45;U++){await new Promise(
|
|
291
|
+
`),process.stdout.write("\u23F3 Waiting for instance to start");for(let U=0;U<45;U++){await new Promise(z=>setTimeout(z,3e3)),process.stdout.write(".");try{const z=await fetch(`${x}/api/v1/instances/${R}`,{headers:{Authorization:`Bearer ${b}`}});if(z.ok){const ee=await z.json();if(ee.status==="running"){p=[ee];break}}}catch{}}console.log("")}}catch(f){console.log(` failed: ${f.message}
|
|
292
292
|
`)}p.length===0&&(console.error(`
|
|
293
293
|
Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
|
|
294
294
|
`),ce(j("/instances",u)),w.close(),process.exit(1))}const i=p[0];p.length>1&&(console.log(`\u2139\uFE0F Multiple instances found \u2014 using most recent: ${i.name}`),console.log(` (Run with --instance-id <id> to use a different one)
|
|
295
295
|
`)),console.log(`\u2713 Instance: ${i.name} (${i.id.slice(0,8)}\u2026)
|
|
296
296
|
`),S("setup_instance_ready",{instance_id:i.id});const d=process.cwd(),h=[],{homedir:T}=await import("node:os"),L=T();h.push("claude"),n(o(d,".cursor"))&&h.push("cursor"),n(o(d,".windsurf"))&&h.push("windsurf"),n(o(d,".vscode"))&&h.push("copilot"),n(o(d,".continue"))&&h.push("continue");const E=process.platform==="darwin"?o(L,"Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev"):o(L,".vscode/extensions");(n(E)&&!h.includes("copilot")||n(E))&&h.push("cline");const A=process.platform==="darwin"?o(L,"Library/Application Support/Zed"):o(L,".config/zed");n(A)&&h.push("zed");const C=f=>({claude:"Claude Code",cursor:"Cursor",windsurf:"Windsurf",copilot:"GitHub Copilot",continue:"Continue.dev",cline:"Cline (VSCode)",zed:"Zed"})[f]??f,I=h;console.log(`Step 3: Configuring for: ${I.map(C).join(", ")}
|
|
297
|
-
`);const{existsSync:$}=await import("node:fs"),k=[];let
|
|
298
|
-
\u23F3 Fetching your Brain health preview...`);try{const f=await fetch(`${x}/api/v1/instances/${i.id}/memory`,{headers:{Authorization:`Bearer ${b}`},signal:AbortSignal.timeout(6e3)});if(f.ok){const _=await f.json(),R=_.lesson_count??0,U=_.context_count??0,
|
|
299
|
-
`),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F9E0} Brain Health Report \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Lessons stored : ${String(R).padEnd(6)} \u2502 Level: ${ee.padEnd(20)}\u2502`),console.log(`\u2502 Context entries : ${String(U).padEnd(6)} \u2502 Quality score: ${String(
|
|
300
|
-
\u23F3 Running predictive risk scan...`);try{const B=(await
|
|
297
|
+
`);const{existsSync:$}=await import("node:fs"),k=[];let N=0;Q(b);for(const f of I){const _=me[f]??".mcp.json",R=o(d,_);try{await t(c(R),{recursive:!0});const U=$(R),z=await Lt(R,b,i.id,f,{readFile:s,existsSync:$});await e(R,z,"utf-8"),console.log(`\u2705 ${U?"Updated":"Written"}: ${_}`),N++}catch(U){const z=U.message;console.log(`\u26A0\uFE0F Could not write ${_}: ${z}`),console.log(" Fix permissions or run with sudo, then re-run setup."),k.push({file:_,reason:z})}}const Y=o(L,".claude","mcp.json");try{await t(c(Y),{recursive:!0});let f={};if(n(Y))try{f=JSON.parse(await s(Y,"utf-8"))}catch{}f.mcpServers??={},f.mcpServers.cachly={command:"npx",args:["-y","@cachly-dev/mcp-server@latest"],env:se(b,i.id,{includeApiKey:!0})},await e(Y,JSON.stringify(f,null,2),"utf-8"),console.log("\u2705 Written: ~/.claude/mcp.json (global \u2014 works in every project)"),N++}catch(f){const _=f.message;console.log(`\u26A0\uFE0F Could not write ~/.claude/mcp.json: ${_}`),k.push({file:"~/.claude/mcp.json",reason:_})}const K=await Nt(d,i.id);for(const[f,_]of Object.entries(K))console.log(`${_==="updated"?"\u2705 Updated":_==="appended"?"\u2705 Appended to":"\u2705 Written"}: ${f}`);y=b;let be=0;if(n(o(d,".git"))){process.stdout.write("\u23F3 Bootstrapping Brain from git history (~10s)...");try{const f=await J("brain_from_git",{instance_id:i.id,repo_path:d,limit:100}),_=f.match(/Ingested: \*\*(\d+)\*\*/);be=_?parseInt(_[1],10):0,console.log(` \u2713 ${be} lesson${be===1?"":"s"} extracted from git history`);const R=Ho(f);R&&(console.log(""),console.log(R))}catch(f){console.log(` (skipped: ${f.message.slice(0,80)})`)}}if(be===0){process.stdout.write("\u{1F331} Seeding 16 universal engineering lessons (first recall works instantly)...");try{await J("brain_seed_starter",{instance_id:i.id}),console.log(" \u2713");try{const f=await J("smart_recall",{instance_id:i.id,query:"docker build slow"}),_=Zn(f);_&&(console.log(""),console.log(Mo(_.topic,_.what)))}catch{}}catch(f){console.log(` (skipped: ${f.message.slice(0,60)})`)}}process.stdout.write(`
|
|
298
|
+
\u23F3 Fetching your Brain health preview...`);try{const f=await fetch(`${x}/api/v1/instances/${i.id}/memory`,{headers:{Authorization:`Bearer ${b}`},signal:AbortSignal.timeout(6e3)});if(f.ok){const _=await f.json(),R=_.lesson_count??0,U=_.context_count??0,z=Math.round(_.iq_boost_pct??0),ee=R===0?"Intern \u{1F331}":R<10?"Junior Dev \u{1F527}":R<30?"Mid Dev \u26A1":R<60?"Senior Dev \u{1F9E0}":R<100?"Staff Eng \u{1F680}":"Principal Eng \u{1F3C6}";if(console.log(` \u2713
|
|
299
|
+
`),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F9E0} Brain Health Report \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log(`\u2502 Lessons stored : ${String(R).padEnd(6)} \u2502 Level: ${ee.padEnd(20)}\u2502`),console.log(`\u2502 Context entries : ${String(U).padEnd(6)} \u2502 Quality score: ${String(z).padEnd(3)}% \u2502`),R===0&&(console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524"),console.log("\u2502 Your Brain is empty and ready to learn. \u2502"),console.log("\u2502 After your first coding session it will contain: \u2502"),console.log("\u2502 \u2022 Lessons from every bug you fixed \u2502"),console.log("\u2502 \u2022 Your project's indexed files \u2502"),console.log("\u2502 \u2022 A session summary for next time \u2502")),console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518"),R>=5){process.stdout.write(`
|
|
300
|
+
\u23F3 Running predictive risk scan...`);try{const B=(await J("brain_predict",{instance_id:i.id,context:"starting a new development session"})).split(`
|
|
301
301
|
`).filter(M=>M.trim()).slice(0,6);if(B.length>0){console.log(` \u2713
|
|
302
302
|
`),console.log("\u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510"),console.log("\u2502 \u{1F52E} Brain Risk Preview (brain_predict) \u2502"),console.log("\u251C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2524");for(const M of B)console.log(`\u2502 ${M.slice(0,51).padEnd(51)} \u2502`);console.log("\u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")}else console.log(" (no risks found \u2014 clean slate!)")}catch{console.log(" (skipped)")}}}else console.log(" (skipped)")}catch{console.log(" (skipped)")}if(console.log(`
|
|
303
303
|
\u{1F389} Your AI just got a permanent brain.`),console.log(` Restart your editor \u2014 from this session on, it arrives pre-briefed.
|
|
@@ -305,14 +305,14 @@ Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
|
|
|
305
305
|
`),console.log(` Dashboard: ${j(`/instances/${i.id}`,u)}`),console.log(`
|
|
306
306
|
\u{1F4DB} Add a live badge to your README:`),console.log(` npx @cachly-dev/mcp-server@latest badge
|
|
307
307
|
`),!g)try{if(console.log(`
|
|
308
|
-
\u{1F451} Governance (optional \u2014 role model: admin \xB7 reviewer \xB7 contributor \xB7 viewer)`),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),(await v(" Set yourself as the first admin? (y/N): ","N")).toLowerCase()==="y"){const _=await v(' Your handle (e.g. "alice"): ');_.trim()&&await
|
|
308
|
+
\u{1F451} Governance (optional \u2014 role model: admin \xB7 reviewer \xB7 contributor \xB7 viewer)`),console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),(await v(" Set yourself as the first admin? (y/N): ","N")).toLowerCase()==="y"){const _=await v(' Your handle (e.g. "alice"): ');_.trim()&&await J("team_assign_role",{instance_id:i.id,handle:_.trim(),role:"admin"}).catch(()=>"")&&(console.log(` \u2705 ${_.trim()} is now admin. Invite teammates:
|
|
309
309
|
`),console.log(` team_assign_role(instance_id="${i.id}", handle="<teammate>", role="contributor", assigned_by="${_.trim()}")
|
|
310
310
|
`))}else console.log(` Skipped \u2014 run team_assign_role at any time.
|
|
311
311
|
`)}catch{}if(!g){const f=await v(" \u{1F4EC} Stay in the loop? Email for release notes [Enter to skip]: ");if(f&&f.includes("@"))try{await fetch(`${x}/api/newsletter/subscribe`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({email:f.trim().toLowerCase(),source:"mcp-setup"}),signal:AbortSignal.timeout(5e3)}),console.log(` \u2705 Subscribed \u2014 you'll only hear from us when it matters.
|
|
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);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:
|
|
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:N}),S("setup_completed",{instance_id:i.id,elapsed_s:Me,config_failures:k.length}),k.length>0&&N===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)}
|
|
@@ -323,7 +323,7 @@ Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
|
|
|
323
323
|
`),console.error(" export CACHLY_BRAIN_INSTANCE_ID=<uuid>"),console.error(" export CACHLY_JWT=<cky_live_...>"),console.error(` npx @cachly-dev/mcp-server@latest index ./my-project
|
|
324
324
|
`),process.exit(1)),console.log(`
|
|
325
325
|
\u{1F4C2} Indexing: ${n}`),console.log(` Instance: ${o.slice(0,8)}\u2026 Max files: ${c}
|
|
326
|
-
`);try{const a=await
|
|
326
|
+
`);try{const a=await J("index_project",{instance_id:o,dir:n,max_files:c,ttl:604800,namespace:r});console.log(a),console.log(`
|
|
327
327
|
\u2705 Indexing complete.
|
|
328
328
|
`)}catch(a){console.error(`
|
|
329
329
|
\u274C Indexing failed: ${a.message}
|
|
@@ -332,17 +332,18 @@ Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
|
|
|
332
332
|
`),console.error(" export CACHLY_BRAIN_INSTANCE_ID=<uuid>"),console.error(" export CACHLY_JWT=<cky_live_...>"),console.error(` npx @cachly-dev/mcp-server@latest learn-git .
|
|
333
333
|
`),process.exit(1)),console.log(`
|
|
334
334
|
\u{1F9E0} Learning from git history: ${n}`),console.log(` Instance: ${o.slice(0,8)}\u2026 Max commits: ${c}
|
|
335
|
-
`);try{const r=await
|
|
335
|
+
`);try{const r=await J("brain_from_git",{instance_id:o,repo_path:n,limit:c});console.log(r),S("brain_from_git",{api_key:y,instance_id:o}),console.log(`
|
|
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
|
|
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,instanz:F()||void 0};await nn(n),await Xn(process.env.CACHLY_BRAIN_INSTANCE_ID??O,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=F(),t=an(await lt(),e||void 0),s=t.eigene,n=Yn(s),o=s.slice(-5);if(console.log(`
|
|
340
340
|
\u{1F9E0} Ambient Recall \u2014 net-token ledger
|
|
341
|
-
`),console.log(` Turns recorded: ${
|
|
342
|
-
Last entries:`);for(const
|
|
341
|
+
`),console.log(` Instance: ${e?`${e.slice(0,8)}\u2026`:"(none set \u2014 showing every entry on this computer)"}`),console.log(` Turns recorded: ${s.length}`),console.log(` Injected tokens: ${n.injected}`),console.log(` Prevented tokens: ${n.prevented} (agent-reported via ambient-credit)`),console.log(` NET: ${n.net>=0?"+":""}${n.net} tokens`),o.length>0){console.log(`
|
|
342
|
+
Last entries:`);for(const c of o){const r=c.prevented>0?`+${c.prevented} prevented`:`-${c.injected} injected`;console.log(` \u2022 ${c.ts.slice(0,19)} ${c.event}: ${r}${c.note?` (${c.note})`:""}`)}}(t.ohneInstanz>0||t.andereInstanzen>0)&&(console.log(`
|
|
343
|
+
Not counted above:`),t.ohneInstanz>0&&console.log(` \u2022 ${t.ohneInstanz} older entries without an instance (before 0.10.207)`),t.andereInstanzen>0&&console.log(` \u2022 entries of ${t.andereInstanzen} other instance${t.andereInstanzen===1?"":"s"} on this computer`)),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 zo(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()||O),await c(x,y,F()||O),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??O;(!s||!t.source)&&process.exit(0),await J("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(zt(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
344
|
`))}else process.stderr.write(`\u26A0\uFE0F cachly: client_credentials auth failed (${t.status}). Check CACHLY_CLIENT_ID / CACHLY_CLIENT_SECRET.
|
|
344
345
|
`),S("m2m_auth_failed",{status:t.status})}catch(t){process.stderr.write(`\u26A0\uFE0F cachly: client_credentials auth error: ${t.message}
|
|
345
|
-
`),S("m2m_auth_failed",{reason:"network"})}}const
|
|
346
|
+
`),S("m2m_auth_failed",{reason:"network"})}}const ys=["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&&!ys.includes(process.argv[2]??""))if(!process.argv[2]&&process.stdout.isTTY===!0&&Gt){const n=`
|
|
346
347
|
\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
347
348
|
\u2551 \u{1F9E0} cachly AI Brain \u2014 Setup required \u2551
|
|
348
349
|
\u2560\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\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2563
|
|
@@ -370,7 +371,7 @@ Could not create an instance automatically. Opening ${j("/instances",u)} \u2026
|
|
|
370
371
|
\u26A0\uFE0F cachly: CACHLY_JWT expires in ${t} minute(s).
|
|
371
372
|
Refresh it soon at ${j("/setup-ai","jwt-expiry")} to avoid interruptions.
|
|
372
373
|
|
|
373
|
-
`)}}process.env.PORT||
|
|
374
|
+
`)}}process.env.PORT||jn({aktuelle:Rn(D)});const ke=process.env.PORT?parseInt(process.env.PORT,10):void 0;if(ke){const{createServer:e}=await import("node:http");e((s,n)=>{const o=new URL(s.url??"/",`http://localhost:${ke}`);if(o.pathname==="/health"){n.writeHead(200,{"Content-Type":"application/json"}),n.end(JSON.stringify({status:"ok",version:D,zeroResults:{total:Ao,last10:So.slice(-10).map(c=>({query:c.query,ts:new Date(c.ts).toISOString()}))}}));return}if(o.pathname==="/mcp"||o.pathname==="/"){(async()=>{const c=ds(),r=new Zt({sessionIdGenerator:void 0});n.on("close",()=>{r.close().catch(()=>{}),c.close().catch(()=>{})});try{await c.connect(r),await r.handleRequest(s,n)}catch(a){process.stderr.write(`cachly-mcp HTTP: ${a.message}
|
|
374
375
|
`),n.headersSent||(n.writeHead(500,{"Content-Type":"application/json"}),n.end(JSON.stringify({error:a.message})))}})();return}n.writeHead(404),n.end("not found")}).listen(ke,()=>{process.stderr.write(`cachly-mcp HTTP server listening on :${ke}
|
|
375
|
-
`)})}else{const e=new Vt;W("start: Module geladen, stdio verbinden"),await V.connect(e),typeof process.argv[2]=="string"&&!process.argv[2].startsWith("-")||(Ze=!0,so(),On(),
|
|
376
|
-
`),(async()=>{await He().catch(()=>{});for(const[,n]of ne)await n.quit().catch(()=>{});process.exit(0)})()}))}
|
|
376
|
+
`)})}else{const e=new Vt;W("start: Module geladen, stdio verbinden"),await V.connect(e),typeof process.argv[2]=="string"&&!process.argv[2].startsWith("-")||(Ze=!0,so(),On(),Ln(process.stdin,s=>{process.stderr.write(`[cachly-mcp] ${s} \u2014 Session zu Ende, Server geht mit
|
|
377
|
+
`),(async()=>{await He().catch(()=>{});for(const[,n]of ne)await n.quit().catch(()=>{});process.exit(0)})()}))}ze("cachly","startup",{version:D,mode:process.env.MCP_HTTP_PORT?"http":"stdio"}).catch(()=>{});export{it as CLAUDE_MD_MARKER_END,st as CLAUDE_MD_MARKER_START,ko as CROSS_LINGUAL_MAP,me as EDITOR_FILES,wo as STOPWORDS,_o as arabicLightStem,gs as buildClaudeMdBlock,ms as buildMcpConfig,se as buildServerEnv,$o as expandCrossLingual,vo as extractTimestamp,xo as katakanaToRomaji,yo as levenshtein,ps as mcpAddBefehl,Lt as mergeMcpConfig,bo as recencyBoost,Co as reconnectOnce,ho as splitMultiQuery,uo as startBackgroundDevicePoll,fo as tokenize,Nt as writeInstructions};
|