@cachly-dev/mcp-server 0.10.172 → 0.10.174

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -340,9 +340,9 @@ MCP tool — bulk-ingests past outcomes the same way `brain_from_git` ingests co
340
340
 
341
341
  ---
342
342
 
343
- ## MCP Tools (123 total, 27 in the default catalogue)
343
+ ## MCP Tools (124 total, 27 in the default catalogue)
344
344
 
345
- **Your editor sees 27 of them, not 123 — on purpose.** The full list cost
345
+ **Your editor sees 27 of them, not 124 — on purpose.** The full list cost
346
346
  ~27,750 tokens in *every* request, which is 14 % of a 200k window gone before
347
347
  you type anything. The tools you use daily are listed individually; the other
348
348
  96 sit behind one dispatcher:
@@ -354,7 +354,7 @@ cachly_tool(tool: "team_roster", describe: true) get its schema first
354
354
 
355
355
  Nothing is unreachable: the server dispatches by name and never consults the
356
356
  catalogue, so `team_roster` called directly still works. Set
357
- `CACHLY_ALLE_WERKZEUGE=1` to get all 123 listed again.
357
+ `CACHLY_ALLE_WERKZEUGE=1` to get all 124 listed again.
358
358
 
359
359
  The full tool catalog is generated from `sdk/mcp/src/tools.ts`. Cross-surface
360
360
  coverage is tracked in [`../../docs/generated/surface-parity.md`](../../docs/generated/surface-parity.md),
@@ -1,7 +1,2 @@
1
- import{decideRecall as p,commitInjection as h,emptyMemory as g,isTrivialPrompt as y,selectInjectable as d,estimateTokens as l}from"./ambient-recall.js";import{rahmeEin as b}from"./einblendung-rahmen.js";function v(e){const t=(e??"").trim();if(!t)return null;try{const r=JSON.parse(t);return r&&typeof r=="object"?r:null}catch{return null}}const S=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function k(e){const t=e.hook_event_name??"UserPromptSubmit";if(t==="SessionStart")return e.source==="compact"||e.source==="clear"?null:"session start: recent lessons, active pitfalls, and known failure modes for this project";if(t==="PreToolUse"){if(e.tool_name&&!S.has(e.tool_name))return null;const n=e.tool_input?.file_path;return typeof n!="string"||!n.trim()?null:`known pitfalls, past bugs and lessons for file ${n.trim()}`}if(t==="Stop")return null;const r=(e.prompt??"").trim();return!r||y(r)?null:r}const w=/\b(fixed|resolved|behoben|gefixt|root cause|the bug was|der fehler (lag|war)|ursache (war|gefunden)|now passes|tests? (are|is|sind) (green|grün)|deployed successfully)\b/i;function O(e){const t=(e.last_assistant_message??"").trim();return t.length<80||!w.test(t)?null:{action:(t.split(`
2
- `).find(n=>n.trim().length>0)?.trim()??t).slice(0,200),outcome:"success",details:t.slice(0,500),severity:"minor"}}function $(e,t){const r=e.trim();if(l(r)<=t)return r;const n=Math.max(0,t*4),o=r.slice(0,n),i=o.lastIndexOf(" ");return(i>n*.6?o.slice(0,i):o).trimEnd()+"\u2026"}const x="(If this memory just saved you from a wrong path, record it: `npx @cachly-dev/mcp-server@latest ambient-credit <tokens-saved>`)";function _(e){const t=[];if(e.learnedAt){const r=new Date(e.learnedAt);Number.isNaN(r.getTime())||t.push(`am ${String(r.getDate()).padStart(2,"0")}.${String(r.getMonth()+1).padStart(2,"0")}.`)}if(e.files?.length){const r=e.files.slice(0,2).join(", ");t.push(`in ${r}${e.files.length>2?` (+${e.files.length-2})`:""}`)}return e.outcome==="failure"?t.push("ging damals schief"):e.outcome==="success"&&t.push("so ging es damals gut aus"),t.length?` \u21B3 ${t.join(" \xB7 ")}`:""}function T(e,t=!1){if(e.length===0)return"";const r=e.length===1&&e[0].summary.includes(`
3
- `)?e[0].summary.trim():`\u{1F9E0} Relevant memory from your cachly brain (auto-recalled):
4
- `+e.map(o=>{const i=_(o);return`- ${o.summary.trim()}`+(i?`
5
- `+i:"")}).join(`
6
- `),n=b(r);return t?`${n}
7
- ${x}`:n}function P(e,t){return t?JSON.stringify({hookSpecificOutput:{hookEventName:e,additionalContext:t}}):""}async function j(e,t,r){let n;const o=new Promise(i=>{n=setTimeout(()=>i(r),t)});try{return await Promise.race([e,o])}finally{n&&clearTimeout(n)}}async function M(e,t){const r=v(e);if(!r)return"";const n=r.hook_event_name??"UserPromptSubmit",o=k(r);if(o===null)return"";try{if(t.backoff&&await t.backoff())return""}catch{}let i=[];try{i=await j(t.recall(o,n),t.timeoutMs??3e3,[])}catch{return""}if(!Array.isArray(i)||i.length===0)return"";const c=n==="UserPromptSubmit"?r.prompt??o:o,a=t.loadMemory?.()??g(),s=t.loadMemory?p(c,i,a,t.gate):{...d(c,i,t.gate),risk:"normal",suppressedDuplicates:[]};if(t.saveMemory)try{t.saveMemory(h(a,s))}catch{}if(!s.inject)return"";const m=n==="UserPromptSubmit"||n==="PreToolUse",u=T(s.selected,m),f=l(u);try{t.onInject?.(f,n)}catch{}return P(n,u)}export{x as CREDIT_FOOTER,P as buildHookOutput,T as formatContextBlock,_ as formatProvenance,v as parseHookPayload,k as recallQueryFor,M as runAmbient,O as stopObservation,$ as truncateToTokens};
1
+ import{promptEinblendung as l,holeBestand as u,sitzungsKontext as c,hookAusgabe as i,estimateTokens as f}from"./einblendung.js";function a(e){const t=(e??"").trim();if(!t)return null;try{const n=JSON.parse(t);return n&&typeof n=="object"?n:null}catch{return null}}const m=new Set(["Edit","Write","MultiEdit","NotebookEdit"]);function p(e){const t=e.hook_event_name??"UserPromptSubmit";if(t==="SessionStart"||t==="Stop")return null;if(t==="PreToolUse"){if(e.tool_name&&!m.has(e.tool_name))return null;const r=e.tool_input?.file_path;if(typeof r!="string"||!r.trim())return null;const o=r.trim().replace(/\\/g,"/"),s=(e.cwd??"").replace(/\\/g,"/").replace(/\/+$/,"");return s&&o.toLowerCase().startsWith(s.toLowerCase()+"/")?o.slice(s.length+1):o}return(e.prompt??"").trim()||null}const g=/\b(fixed|resolved|behoben|gefixt|root cause|the bug was|der fehler (lag|war)|ursache (war|gefunden)|now passes|tests? (are|is|sind) (green|grün)|deployed successfully)\b/i;function w(e){const t=(e.last_assistant_message??"").trim();return t.length<80||!g.test(t)?null:{action:(t.split(`
2
+ `).find(r=>r.trim().length>0)?.trim()??t).slice(0,200),outcome:"success",details:t.slice(0,500),severity:"minor"}}const S=i,h=5e3;async function k(e,t){try{const n=a(e);if(!n)return"";const r=n.hook_event_name??"UserPromptSubmit";if(!t.cfg.jwt||!t.cfg.instanceId)return"";let o="";if(r==="SessionStart"){const{lessons:s}=await u(t.cfg,{force:!0,fetchFn:t.fetchFn});o=c(s)}else{const s=p(n);if(s===null)return"";o=(await l(s,t.cfg,{nebenlauf:t.nebenlauf,abrufMs:h,leser:r!=="PreToolUse",session:n.session_id??null,protokoll:t.protokoll,fetchFn:t.fetchFn})).kontext}if(!o)return"";try{t.onInject?.(f(o),r)}catch{}return i(r,o)}catch{return""}}export{h as PROMPT_ABRUF_MS,S as buildHookOutput,a as parseHookPayload,p as recallQueryFor,k as runEinblendung,w as stopObservation};
@@ -0,0 +1 @@
1
+ import{rahmeEin as a}from"./einblendung-rahmen.js";const t=new Set(["session_start","session_start_summary","smart_recall","recall_best_solution","recall_context","list_remembered","recall_at","compact_recover","brain_briefing","semantic_search","brain_search","causal_trace","team_recall","global_recall","fedbrain_search","syndicate_search","syndicate_trending","brain_discover","brain_predict","brain_predict_failures","brain_plan","brain_changelog","brain_conflicts","crystal_view","memory_crystalize","team_crystallize","team_synthesize"]);function s(e,r){return t.has(e)&&a(r)||r}export{t as GERAHMTE_WERKZEUGE,s as rahmeAntwort};
@@ -1,2 +1,2 @@
1
- import{existsSync as f,readFileSync as p}from"node:fs";import{resolve as g}from"node:path";import{AMBIENT_HOOK_VERSION as l}from"./ambient-hooks.js";import{netBalance as y,shouldBackoff as v}from"./ambient-recall.js";import{cachlyUrl as $}from"./cachly-url.js";const k=18;function H(t=process.version){const e=Number(t.replace(/^v/,"").split(".")[0]);return Number.isFinite(e)&&e>=k?{name:"Node.js",status:"ok",detail:`${t}`}:{name:"Node.js",status:"fail",detail:`${t} \u2014 too old`,hint:`cachly needs Node ${k}+ (built-in fetch). Install a current LTS from nodejs.org.`}}function P(t){if(!t)return{name:"Credential",status:"fail",detail:"CACHLY_JWT is not set",hint:"Run `npx @cachly-dev/mcp-server@latest autopilot` (browser sign-in) or export CACHLY_JWT=<cky_\u2026>."};const e=t.startsWith("cky_"),s=t.split(".").length===3;return!e&&!s?{name:"Credential",status:"warn",detail:"CACHLY_JWT is set but looks neither like a cky_\u2026 key nor a JWT",hint:"Re-copy the key from the dashboard (API Keys) \u2014 it may be truncated."}:{name:"Credential",status:"ok",detail:e?"API key (cky_\u2026)":"JWT"}}async function R(t,e=fetch){try{const s=await e(`${t}/health`,{signal:AbortSignal.timeout(5e3)});return s.ok?{name:"API",status:"ok",detail:`${t} reachable`}:{name:"API",status:"fail",detail:`${t}/health returned HTTP ${s.status}`,hint:`The API answered but is unhealthy \u2014 check ${$("/status","doctor")} or your CACHLY_API_URL.`}}catch{return{name:"API",status:"fail",detail:`${t} not reachable`,hint:"Check your network/proxy. Self-hosted: is CACHLY_API_URL correct and the API running?"}}}async function S(t,e,s=fetch){if(!e)return{name:"Auth",status:"fail",detail:"skipped \u2014 no credential",hint:"Fix the Credential check first."};try{const r=await s(`${t}/api/v1/instances`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(5e3)});return r.ok?{name:"Auth",status:"ok",detail:"credential accepted"}:r.status===401||r.status===403?{name:"Auth",status:"fail",detail:`API rejected the credential (HTTP ${r.status})`,hint:"The key is expired or revoked. Create a new one in the dashboard, or re-run autopilot."}:{name:"Auth",status:"warn",detail:`unexpected HTTP ${r.status} from /api/v1/instances`}}catch{return{name:"Auth",status:"warn",detail:"could not verify (network error)"}}}async function L(t,e,s,r=fetch){if(!e||!s)return{name:"Vektoren",status:"warn",detail:"skipped \u2014 no credential or instance"};try{const n=await r(`${t}/api/v1/instances/${s}/vector-coverage`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(12e3)});if(!n.ok)return{name:"Vektoren",status:"warn",detail:`coverage not measured (HTTP ${n.status})`};const a=await n.json();return a.status==="leer"?{name:"Vektoren",status:"ok",detail:"no lessons yet"}:a.status==="nicht-gemessen"?{name:"Vektoren",status:"warn",detail:"instance not running \u2014 not measured"}:a.status==="aus"?{name:"Vektoren",status:"fail",detail:`semantic search is OFF: ${a.lessons} lessons, 0 vectors`,hint:"Embeddings never ran for this instance. Check the embed provider; recall runs word-only until fixed."}:a.status==="luecke"?{name:"Vektoren",status:"warn",detail:`${a.vectors}/${a.lessons} lessons have vectors (${a.percent.toFixed(0)}%)`,hint:"Some lessons are invisible to semantic search. Large writes under the rate limit can skip embedding."}:{name:"Vektoren",status:"ok",detail:`${a.vectors}/${a.lessons} vectors (${a.percent.toFixed(0)}%)`}}catch{return{name:"Vektoren",status:"warn",detail:"could not verify (network error)"}}}function V(t){return t?/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(t)?{name:"Instance",status:"ok",detail:t.slice(0,8)+"\u2026"}:{name:"Instance",status:"warn",detail:`"${t.slice(0,24)}" does not look like an instance UUID`,hint:"Copy the instance ID from the dashboard (Instances \u2192 your brain)."}:{name:"Instance",status:"warn",detail:"no CACHLY_BRAIN_INSTANCE_ID set and no default instance resolved",hint:"Run `npx @cachly-dev/mcp-server@latest init` in your project, or export CACHLY_BRAIN_INSTANCE_ID."}}function j(t){const e={settingsExists:!1,wiredEvents:[],scriptFiles:[]};try{const s=g(t,".claude/settings.json");if(e.settingsExists=f(s),e.settingsExists){const r=JSON.parse(p(s,"utf-8"));for(const[n,a]of Object.entries(r.hooks??{})){const u=o=>(o??"").replace(/\\/g,"/");if((a??[]).some(o=>(o.hooks??[]).some(i=>u(i.command).includes(".claude/hooks/cachly-ambient-")))){e.wiredEvents.push(n);for(const o of a??[])for(const i of o.hooks??[]){const h=u(i.command).match(/["']?([^"']*\.claude\/hooks\/cachly-ambient-[^"']+)["']?/);if(!h)continue;const c=h[1].replace("$CLAUDE_PROJECT_DIR",t),d=f(c);let m="unknown";if(d)try{m=p(c,"utf-8").includes(l)?"current":"stale"}catch{}e.scriptFiles.push({path:c,exists:d,version:m})}}}}}catch{}return e}const A=["SessionStart","UserPromptSubmit","PreToolUse","Stop"];function F(t){if(!t.settingsExists||t.wiredEvents.length===0)return{name:"Hooks",status:"warn",detail:"Ambient Recall hooks are not installed in this project",hint:"Run `npx @cachly-dev/mcp-server@latest init` here \u2014 memory then injects itself (no hooks = pull-only)."};const e=A.filter(n=>!t.wiredEvents.includes(n)),s=t.scriptFiles.filter(n=>!n.exists),r=t.scriptFiles.filter(n=>n.exists&&n.version==="stale");return s.length>0?{name:"Hooks",status:"fail",detail:`settings.json wires hooks whose script files are missing (${s.length})`,hint:"Re-run `npx @cachly-dev/mcp-server@latest init` to rewrite the scripts."}:r.length>0?{name:"Hooks",status:"warn",detail:`installed hooks are an older version (current: ${l}); v1/v2 shell hooks never ran on native Windows`,hint:"Re-run `npx @cachly-dev/mcp-server@latest init` to upgrade in place."}:e.length>0?{name:"Hooks",status:"warn",detail:`partial install \u2014 missing events: ${e.join(", ")}`,hint:"Re-run `npx @cachly-dev/mcp-server@latest init` to add the missing hooks."}:{name:"Hooks",status:"ok",detail:`all 4 events wired, scripts ${l}`}}function O(t,e){const s=y(t),r=v(t);return t.length===0?{name:"Ledger",status:"ok",detail:`empty (${e}) \u2014 fills up once ambient hooks inject`}:r?{name:"Ledger",status:"warn",detail:`${t.length} entries, net ${s.net} tokens \u2014 auto-backoff ACTIVE, injection paused`,hint:"The agent has not reported prevented tokens lately. This self-heals; `ambient-stats` shows details."}:{name:"Ledger",status:"ok",detail:`${t.length} entries, net ${s.net>=0?"+":""}${s.net} tokens`}}const w={ok:"\u2705",warn:"\u26A0\uFE0F ",fail:"\u274C"};function J(t){const e=["","\u{1FA7A} cachly doctor",""];for(const n of t)e.push(` ${w[n.status]} ${n.name.padEnd(11)} ${n.detail}`),n.hint&&n.status!=="ok"&&e.push(` \u21B3 ${n.hint}`);const s=t.filter(n=>n.status==="fail").length,r=t.filter(n=>n.status==="warn").length;return e.push(""),e.push(s>0?` ${s} problem${s>1?"s":""} to fix${r?`, ${r} warning${r>1?"s":""}`:""}.`:r>0?` No blockers \u2014 ${r} warning${r>1?"s":""}.`:" Everything looks healthy. Your brain is wired."),e.push(""),e.join(`
2
- `)}function B(t){return t.some(e=>e.status==="fail")?1:0}export{R as checkApiReachable,S as checkAuthAccepted,P as checkCredential,F as checkHooks,V as checkInstance,O as checkLedger,H as checkNodeVersion,L as checkVectorCoverage,B as doctorExitCode,j as inspectAmbientHooks,J as renderDoctorReport};
1
+ import{existsSync as f,readFileSync as p}from"node:fs";import{resolve as y}from"node:path";import{AMBIENT_HOOK_VERSION as l}from"./ambient-hooks.js";import{netBalance as g}from"./ambient-recall.js";import{cachlyUrl as v}from"./cachly-url.js";const k=18;function N(t=process.version){const e=Number(t.replace(/^v/,"").split(".")[0]);return Number.isFinite(e)&&e>=k?{name:"Node.js",status:"ok",detail:`${t}`}:{name:"Node.js",status:"fail",detail:`${t} \u2014 too old`,hint:`cachly needs Node ${k}+ (built-in fetch). Install a current LTS from nodejs.org.`}}function H(t){if(!t)return{name:"Credential",status:"fail",detail:"CACHLY_JWT is not set",hint:"Run `npx @cachly-dev/mcp-server@latest autopilot` (browser sign-in) or export CACHLY_JWT=<cky_\u2026>."};const e=t.startsWith("cky_"),n=t.split(".").length===3;return!e&&!n?{name:"Credential",status:"warn",detail:"CACHLY_JWT is set but looks neither like a cky_\u2026 key nor a JWT",hint:"Re-copy the key from the dashboard (API Keys) \u2014 it may be truncated."}:{name:"Credential",status:"ok",detail:e?"API key (cky_\u2026)":"JWT"}}async function P(t,e=fetch){try{const n=await e(`${t}/health`,{signal:AbortSignal.timeout(5e3)});return n.ok?{name:"API",status:"ok",detail:`${t} reachable`}:{name:"API",status:"fail",detail:`${t}/health returned HTTP ${n.status}`,hint:`The API answered but is unhealthy \u2014 check ${v("/status","doctor")} or your CACHLY_API_URL.`}}catch{return{name:"API",status:"fail",detail:`${t} not reachable`,hint:"Check your network/proxy. Self-hosted: is CACHLY_API_URL correct and the API running?"}}}async function R(t,e,n=fetch){if(!e)return{name:"Auth",status:"fail",detail:"skipped \u2014 no credential",hint:"Fix the Credential check first."};try{const r=await n(`${t}/api/v1/instances`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(5e3)});return r.ok?{name:"Auth",status:"ok",detail:"credential accepted"}:r.status===401||r.status===403?{name:"Auth",status:"fail",detail:`API rejected the credential (HTTP ${r.status})`,hint:"The key is expired or revoked. Create a new one in the dashboard, or re-run autopilot."}:{name:"Auth",status:"warn",detail:`unexpected HTTP ${r.status} from /api/v1/instances`}}catch{return{name:"Auth",status:"warn",detail:"could not verify (network error)"}}}async function S(t,e,n,r=fetch){if(!e||!n)return{name:"Vektoren",status:"warn",detail:"skipped \u2014 no credential or instance"};try{const s=await r(`${t}/api/v1/instances/${n}/vector-coverage`,{headers:{Authorization:`Bearer ${e}`},signal:AbortSignal.timeout(12e3)});if(!s.ok)return{name:"Vektoren",status:"warn",detail:`coverage not measured (HTTP ${s.status})`};const a=await s.json();return a.status==="leer"?{name:"Vektoren",status:"ok",detail:"no lessons yet"}:a.status==="nicht-gemessen"?{name:"Vektoren",status:"warn",detail:"instance not running \u2014 not measured"}:a.status==="aus"?{name:"Vektoren",status:"fail",detail:`semantic search is OFF: ${a.lessons} lessons, 0 vectors`,hint:"Embeddings never ran for this instance. Check the embed provider; recall runs word-only until fixed."}:a.status==="luecke"?{name:"Vektoren",status:"warn",detail:`${a.vectors}/${a.lessons} lessons have vectors (${a.percent.toFixed(0)}%)`,hint:"Some lessons are invisible to semantic search. Large writes under the rate limit can skip embedding."}:{name:"Vektoren",status:"ok",detail:`${a.vectors}/${a.lessons} vectors (${a.percent.toFixed(0)}%)`}}catch{return{name:"Vektoren",status:"warn",detail:"could not verify (network error)"}}}function L(t){return t?/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(t)?{name:"Instance",status:"ok",detail:t.slice(0,8)+"\u2026"}:{name:"Instance",status:"warn",detail:`"${t.slice(0,24)}" does not look like an instance UUID`,hint:"Copy the instance ID from the dashboard (Instances \u2192 your brain)."}:{name:"Instance",status:"warn",detail:"no CACHLY_BRAIN_INSTANCE_ID set and no default instance resolved",hint:"Run `npx @cachly-dev/mcp-server@latest init` in your project, or export CACHLY_BRAIN_INSTANCE_ID."}}function F(t){const e={settingsExists:!1,wiredEvents:[],scriptFiles:[]};try{const n=y(t,".claude/settings.json");if(e.settingsExists=f(n),e.settingsExists){const r=JSON.parse(p(n,"utf-8"));for(const[s,a]of Object.entries(r.hooks??{})){const u=o=>(o??"").replace(/\\/g,"/");if((a??[]).some(o=>(o.hooks??[]).some(i=>u(i.command).includes(".claude/hooks/cachly-ambient-")))){e.wiredEvents.push(s);for(const o of a??[])for(const i of o.hooks??[]){const h=u(i.command).match(/["']?([^"']*\.claude\/hooks\/cachly-ambient-[^"']+)["']?/);if(!h)continue;const c=h[1].replace("$CLAUDE_PROJECT_DIR",t),d=f(c);let m="unknown";if(d)try{m=p(c,"utf-8").includes(l)?"current":"stale"}catch{}e.scriptFiles.push({path:c,exists:d,version:m})}}}}}catch{}return e}const $=["SessionStart","UserPromptSubmit","PreToolUse","Stop"];function V(t){if(!t.settingsExists||t.wiredEvents.length===0)return{name:"Hooks",status:"warn",detail:"Ambient Recall hooks are not installed in this project",hint:"Run `npx @cachly-dev/mcp-server@latest init` here \u2014 memory then injects itself (no hooks = pull-only)."};const e=$.filter(s=>!t.wiredEvents.includes(s)),n=t.scriptFiles.filter(s=>!s.exists),r=t.scriptFiles.filter(s=>s.exists&&s.version==="stale");return n.length>0?{name:"Hooks",status:"fail",detail:`settings.json wires hooks whose script files are missing (${n.length})`,hint:"Re-run `npx @cachly-dev/mcp-server@latest init` to rewrite the scripts."}:r.length>0?{name:"Hooks",status:"warn",detail:`installed hooks are an older version (current: ${l}); v1/v2 shell hooks never ran on native Windows`,hint:"Re-run `npx @cachly-dev/mcp-server@latest init` to upgrade in place."}:e.length>0?{name:"Hooks",status:"warn",detail:`partial install \u2014 missing events: ${e.join(", ")}`,hint:"Re-run `npx @cachly-dev/mcp-server@latest init` to add the missing hooks."}:{name:"Hooks",status:"ok",detail:`all 4 events wired, scripts ${l}`}}function j(t,e){const n=g(t);return t.length===0?{name:"Ledger",status:"ok",detail:`empty (${e}) \u2014 fills up once ambient hooks inject`}:{name:"Ledger",status:"ok",detail:`${t.length} entries, net ${n.net>=0?"+":""}${n.net} tokens`}}const A={ok:"\u2705",warn:"\u26A0\uFE0F ",fail:"\u274C"};function O(t){const e=["","\u{1FA7A} cachly doctor",""];for(const s of t)e.push(` ${A[s.status]} ${s.name.padEnd(11)} ${s.detail}`),s.hint&&s.status!=="ok"&&e.push(` \u21B3 ${s.hint}`);const n=t.filter(s=>s.status==="fail").length,r=t.filter(s=>s.status==="warn").length;return e.push(""),e.push(n>0?` ${n} problem${n>1?"s":""} to fix${r?`, ${r} warning${r>1?"s":""}`:""}.`:r>0?` No blockers \u2014 ${r} warning${r>1?"s":""}.`:" Everything looks healthy. Your brain is wired."),e.push(""),e.join(`
2
+ `)}function J(t){return t.some(e=>e.status==="fail")?1:0}export{P as checkApiReachable,R as checkAuthAccepted,H as checkCredential,V as checkHooks,L as checkInstance,j as checkLedger,N as checkNodeVersion,S as checkVectorCoverage,J as doctorExitCode,F as inspectAmbientHooks,O as renderDoctorReport};
@@ -0,0 +1,8 @@
1
+ import{readFileSync as b,existsSync as I,writeFileSync as v,mkdirSync as P,statSync as D,appendFileSync as J}from"node:fs";import{dirname as w,join as h}from"node:path";import{tmpdir as y}from"node:os";import{createHash as Y}from"node:crypto";import{spawn as q}from"node:child_process";import{Einblendbestand as k,torWoerter as N}from"./einblendung-kern.js";import{rahmeEin as x}from"./einblendung-rahmen.js";import{leserText as z}from"./seltenheitsbestand.js";import{mischeMitLeser as L}from"./leser.js";import{LESER_TIEFE as Z,LESER_ZEITLIMIT_MS as F}from"./rangfolge-stellschrauben.js";export*from"./einblendung-kern.js";const K=600*1e3,T=8e3,W=60*1e3,C=120,j=Z,G=1500,R=F,V=h(y(),"cachly-ambient-netlog.jsonl");function Se(e=process.cwd()){const t={apiUrl:process.env.CACHLY_API_URL||"https://api.cachly.dev",jwt:process.env.CACHLY_JWT||"",instanceId:process.env.CACHLY_BRAIN_INSTANCE_ID||""};if(t.jwt&&t.instanceId)return t;let n=e;for(let s=0;s<8;s++){const o=h(n,".mcp.json");if(I(o))try{const i=JSON.parse(b(o,"utf8"))?.mcpServers?.cachly?.env??{};if(t.apiUrl=t.apiUrl||i.CACHLY_API_URL||"https://api.cachly.dev",t.jwt=t.jwt||i.CACHLY_JWT||"",t.instanceId=t.instanceId||i.CACHLY_BRAIN_INSTANCE_ID||"",t.jwt&&t.instanceId)return t}catch{}const r=w(n);if(r===n)break;n=r}return t}function $(e){return Y("sha1").update(e).digest("hex").slice(0,12)}function X(e){return h(y(),`cachly-ambient-bestand-${$(e)}.json`)}function Q(e){return h(y(),`cachly-ambient-auffrischen-${$(e)}.lock`)}async function M(e,{fetchFn:t=fetch,zeitlimitMs:n=T}={}){try{const s=await t(`${e.apiUrl}/api/v1/instances/${e.instanceId}/export`,{headers:{Authorization:`Bearer ${e.jwt}`},signal:AbortSignal.timeout(n)});if(!s.ok)return null;const o=await s.json();return Array.isArray(o?.lessons)?o.lessons.map(r=>typeof r=="string"?ee(r):r).filter(r=>!!r&&typeof r=="object"):null}catch{return null}}function ee(e){try{return JSON.parse(e)}catch{return null}}function O(e,t){try{P(w(e),{recursive:!0}),v(e,JSON.stringify({at:Date.now(),lessons:t}),{mode:384})}catch{}}function H(e){try{const t=JSON.parse(b(e,"utf8"));if(Array.isArray(t?.lessons))return{at:Number(t.at)||0,lessons:t.lessons}}catch{}return null}function te(e,t){const n=Q(e.instanceId);try{if(I(n)&&Date.now()-D(n).mtimeMs<W)return;v(n,String(Date.now()),{mode:384})}catch{return}try{q(process.execPath,t,{detached:!0,stdio:"ignore",env:{...process.env,CACHLY_API_URL:e.apiUrl,CACHLY_JWT:e.jwt,CACHLY_BRAIN_INSTANCE_ID:e.instanceId}}).unref()}catch{}}async function re(e,{force:t=!1,nebenlauf:n,abrufMs:s=T,fetchFn:o}={}){if(!e.jwt||!e.instanceId)return{lessons:[],quelle:"nicht-eingerichtet"};const r=X(e.instanceId);if(t){const a=await M(e,{fetchFn:o,zeitlimitMs:s});if(a)return O(r,a),{lessons:a,quelle:"server"};const u=H(r);return u?{lessons:u.lessons,quelle:"platte-alt"}:{lessons:[],quelle:"server-nicht-erreichbar"}}const i=H(r);if(i){const a=Date.now()-i.at<K;return!a&&n&&te(e,n),{lessons:i.lessons,quelle:a?"platte":"platte-alt"}}const l=await M(e,{fetchFn:o,zeitlimitMs:s});return l?(O(r,l),{lessons:l,quelle:"server"}):{lessons:[],quelle:"server-nicht-erreichbar"}}function _(e){return Math.ceil(String(e).length/4)}function S(e){const t=e.severity?`[${e.severity}] `:"",n=String(e.what_worked??"").replace(/\s+/g," ").trim(),s=n.length>C?`${n.slice(0,C)}\u2026`:n;return`- ${t}${e.topic}: ${s}`}const m={lessons:[],tokens:0,topScore:0,belege:0};function U(e,t,n){const s=[];let o=0;for(const{lektion:r}of e.slice(0,t)){const i=_(S(r));if(o+i>n)break;s.push(r),o+=i}return{lessons:s,tokens:o,topScore:Math.round(e[0].punkte*100)/100,belege:e[0].belege}}function Ee(e,t,{minBelege:n=2,topK:s=3,tokenBudget:o=600}={}){if(!Array.isArray(t)||t.length===0)return{...m};if(N(e).length===0)return{...m};const r=new k(t).sortiere(e).filter(i=>i.belege>=n);return r.length===0?{...m}:U(r,s,o)}function ne(e){return z(e,G)}async function se(e,t,n,{zeitlimitMs:s=R,fetchFn:o=fetch}={}){if(!e?.jwt||!e?.instanceId||n.length===0||["0","off","aus","false"].includes(String(process.env.CACHLY_LESER||"").toLowerCase()))return null;try{const r=await o(`${e.apiUrl}/api/v1/rerank`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e.jwt}`},body:JSON.stringify({query:t,texts:n,instance_id:e.instanceId}),signal:AbortSignal.timeout(s)});if(!r.ok)return null;const i=await r.json(),l=Array.isArray(i.scores)?i.scores:null;return!l||l.length!==n.length||!l.every(a=>typeof a=="number"&&Number.isFinite(a))?null:{scores:l,provider:typeof i.provider=="string"?i.provider:"?",ms:Number(i.ms)||0}}catch{return null}}async function oe(e,t,n,{minBelege:s=2,topK:o=3,tokenBudget:r=600,tiefe:i=j,zeitlimitMs:l=R,fetchFn:a}={}){const u={...m,leser:"aus",leserMs:0};if(!Array.isArray(t)||t.length===0||N(e).length===0)return u;let c=new k(t).sortiere(e).filter(p=>p.belege>=s);if(c.length===0)return u;let E="aus",A=0;if(c.length>1&&i>0){const p=c.slice(0,i),B=c.slice(i),f=await se(n,e,p.map(g=>ne(g.lektion)),{zeitlimitMs:l,fetchFn:a});f&&(c=[...L(p.map(d=>d.punkte),f.scores,1).map(d=>p[d]),...B],E=f.provider,A=f.ms)}return{...U(c,o,r),leser:E,leserMs:A}}function ie(e){if(!e.lessons.length)return"";const t=e.lessons.map(S).join(`
2
+ `);return`\u{1F9E0} Cachly Brain \u2014 relevant lessons for this task (auto-recall, ${e.lessons.length}):
3
+ ${x(t)}
4
+ (ambient-recall \xB7 ~${e.tokens} tokens \xB7 match score ${e.topScore})`}const ae=5;function Ae(e){if(!e.length)return"";const t=e.filter(o=>{const r=String(o.topic??"");return!(/^auto:/.test(r)||/^[a-z]+:?$/.test(r))}),s=[...t.length?t:e].sort((o,r)=>(Number(r.recall_count)||0)-(Number(o.recall_count)||0)).slice(0,ae).map(S).join(`
5
+ `);return`\u{1F9E0} Cachly Brain \u2014 ambient recall active (${e.length} lessons). Top by proven reuse:
6
+ ${x(s)}
7
+ (Relevant lessons for each task are auto-injected per prompt. ~${_(s)} tokens.)`}function ge(e,t){return t?JSON.stringify({hookSpecificOutput:{hookEventName:e,additionalContext:t}}):""}async function be(e,t,{nebenlauf:n,abrufMs:s,leser:o=!0,session:r=null,protokoll:i=!0,fetchFn:l}={}){const{lessons:a,quelle:u}=await re(t,{nebenlauf:n,abrufMs:s,fetchFn:l}),c=await oe(e,a,t,{tiefe:o?j:0,fetchFn:l});if(i)try{J(V,JSON.stringify({at:Date.now(),session:r,prompt_tokens:_(e),injected_tokens:c.tokens,matches:c.lessons.length,top_score:c.topScore,belege:c.belege,leser:c.leser,leser_ms:c.leserMs,quelle:u,bestand:a.length})+`
8
+ `)}catch{}return{kontext:ie(c),auswahl:c,quelle:u,bestand:a.length}}export{T as ABRUF_TIMEOUT_MS,C as ANZEIGE_ZEICHEN,K as BESTAND_TTL_MS,R as LESER_HOOK_ZEITLIMIT_MS,G as LESER_MAX_ZEICHEN,j as LESER_TIEFE,V as NETZ_PROTOKOLL,ae as SITZUNG_TOP_N,X as bestandPfad,_ as estimateTokens,re as holeBestand,ge as hookAusgabe,se as leserPunkteApi,ne as leserText,L as mischeMitLeser,be as promptEinblendung,ie as promptKontext,S as renderLesson,Se as resolveConfig,Ee as selectRelevant,oe as selectRelevantMitLeser,Ae as sitzungsKontext,te as starteNebenlauf};