@cachly-dev/mcp-server 0.10.175 → 0.10.177

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- import{createHmac as oe}from"node:crypto";import{ckgSlug as k,extractProblemConcept as ne,ckgUpsertNode as J,ckgUpdateEdge as T,ckgUpsertPersonNode as ie,ckgUpsertFileNode as ae,ckgRecordCollaboration as ce}from"../ckg.js";import{safeJsonParse as A,normalizeGitPath as re}from"../utils.js";import{buildClsPostCommitHook as le}from"../cls-hook.js";import{installBrainWatchHook as ue}from"../brain-watch-hook.js";import{keywordSearch as de}from"../search.js";import{buildFirstContactReport as Z,suggestRecallQueries as fe}from"../first-contact.js";import{classifyCommit as he,extractDomain as me}from"../commit-art.js";let pe=null,ge=null,U=0;const _e=10,ee=[];function we(){return U<_e?(U++,Promise.resolve()):new Promise(B=>ee.push(B))}function ye(){const B=ee.shift();B?B():U--}const Ne=new Set(["madc_deliberate","cls_ingest","cls_install_hooks","fedbrain_contribute","fedbrain_search","fedbrain_confirm","fedbrain_status","brain_federate","crystal_view","compact_recover","brain_from_git","brain_from_ci","brain_predict_failures","brain_contribute_signal","brain_import_meta","brain_watch"]);async function Ie(B,N,I,K){switch(B){case"madc_deliberate":{const{instance_id:_,topic:i}=N,n=await I(_),e=(await n.lrange(`cachly:lessons:${i}`,0,-1)).map(g=>{try{return JSON.parse(g)}catch{return null}}).filter(Boolean);if(e.length<2)return[`\u{1F5F3}\uFE0F **MADC: "${i}"**`,"",`Not enough history for deliberation (need \u2265 2 entries, found ${e.length}).`,"","Call `learn_from_attempts` with conflicting outcomes to trigger deliberation."].join(`
1
+ import{createHmac as oe}from"node:crypto";import{ckgSlug as k,extractProblemConcept as ne,ckgUpsertNode as J,ckgUpdateEdge as T,ckgUpsertPersonNode as ie,ckgUpsertFileNode as ae,ckgRecordCollaboration as ce}from"../ckg.js";import{safeJsonParse as A,normalizeGitPath as re}from"../utils.js";import{buildClsPostCommitHook as le}from"../cls-hook.js";import{installBrainWatchHook as ue}from"../brain-watch-hook.js";import{keywordSearch as de,wortindexEntwerten as fe}from"../search.js";import{buildFirstContactReport as Z,suggestRecallQueries as he}from"../first-contact.js";import{classifyCommit as me,extractDomain as pe}from"../commit-art.js";let ge=null,_e=null,U=0;const we=10,ee=[];function ye(){return U<we?(U++,Promise.resolve()):new Promise(B=>ee.push(B))}function $e(){const B=ee.shift();B?B():U--}const Ie=new Set(["madc_deliberate","cls_ingest","cls_install_hooks","fedbrain_contribute","fedbrain_search","fedbrain_confirm","fedbrain_status","brain_federate","crystal_view","compact_recover","brain_from_git","brain_from_ci","brain_predict_failures","brain_contribute_signal","brain_import_meta","brain_watch"]);async function Le(B,N,I,K){switch(B){case"madc_deliberate":{const{instance_id:_,topic:i}=N,n=await I(_),e=(await n.lrange(`cachly:lessons:${i}`,0,-1)).map(g=>{try{return JSON.parse(g)}catch{return null}}).filter(Boolean);if(e.length<2)return[`\u{1F5F3}\uFE0F **MADC: "${i}"**`,"",`Not enough history for deliberation (need \u2265 2 entries, found ${e.length}).`,"","Call `learn_from_attempts` with conflicting outcomes to trigger deliberation."].join(`
2
2
  `);const l=[{name:"InfraAgent",domains:["infra","k8s","docker","server","wireguard","helm"]},{name:"AuthAgent",domains:["auth","jwt","keycloak","oauth","oidc","token"]},{name:"DeployAgent",domains:["deploy","ci","pipeline","rsync","release"]},{name:"DatabaseAgent",domains:["db","gorm","migration","postgres","clickhouse","redis"]},{name:"DebugAgent",domains:["debug","panic","race","nil","fix","error"]},{name:"APIAgent",domains:["api","http","grpc","rest","fiber","web"]}],u=i.split(":")[0]??"",c=l.filter(g=>g.domains.some(S=>u===S||i.includes(S))),o=c.length>0?c:l,d=new Map;for(const g of o){let S=0;for(const $ of g.domains){const x=[],v=n.scanStream({match:`cachly:ckg:node:${$}*`,count:50});await new Promise((L,P)=>{v.on("data",R=>x.push(...R)),v.on("end",L),v.on("error",P)}),S+=x.length}d.set(g.name,S)}const h=e.filter(g=>g.outcome==="success"||g.outcome==="partial"),s=e.filter(g=>g.outcome==="failure");if(s.length===0)return[`\u{1F5F3}\uFE0F **MADC: "${i}"**`,"",`No contradictions found \u2014 all ${h.length} entries have non-failure outcomes.`,"",`Use \`ckg_inspect(concept="${k(i)}")\` to explore the confidence graph.`].join(`
3
3
  `);const a=[];for(const g of o){const S=d.get(g.name)??0;let $,x;S<2?($="abstain",x="insufficient domain coverage"):h.length>=s.length*2?($="success",x=`${h.length}/${e.length} entries confirm success`):s.length>=h.length*2?($="failure",x=`${s.length}/${e.length} entries confirm failure`):($="abstain",x=`contested (${h.length} success vs ${s.length} failure)`),a.push({agent:g.name,vote:$,coverage:S,reason:x})}const r=a.filter(g=>g.vote==="success").length,f=a.filter(g=>g.vote==="failure").length,m=a.filter(g=>g.vote==="abstain").length;let p,w;r>0&&f===0?(p="unanimous_success",w=`\u2705 **Unanimous: SUCCESS** \u2014 ${r} agent(s) confirm, ${m} abstain`):f>0&&r===0?(p="unanimous_failure",w=`\u274C **Unanimous: FAILURE** \u2014 ${f} agent(s) confirm, ${m} abstain`):(p="contested",w=`\u26A0\uFE0F **CONTESTED** \u2014 ${r} success votes, ${f} failure votes, ${m} abstain`);const y=k(`resolution:${i}`),j={id:y,domain:"resolution",type:"resolution",count:1,ts:new Date().toISOString(),resolution:p,topic:i,votes:{success:r,failure:f,abstain:m}};if(await n.set(`cachly:ckg:node:${y}`,JSON.stringify(j)),p==="contested")await T(n,k(i),"contradicts",y,!1);else{if(((p==="unanimous_success"?"failure":"success")==="failure"?s:h).length>0){const $=await n.smembers(`cachly:ckg:idx:from:${k(i)}`);for(const x of $){const v=await n.get(x);if(v)try{const L=JSON.parse(v);L.edgeType==="fixes"&&L.confidence>.15&&p==="unanimous_failure"&&(L.confidence=.1,L.last_updated=new Date().toISOString(),await n.set(x,JSON.stringify(L)))}catch{}}}await n.del(`cachly:ckg:conflict:${k(i)}`)}const C=[`\u{1F5F3}\uFE0F **MADC Deliberation: "${i}"**`,"",`\u{1F4CA} Evidence: ${h.length} success/partial vs ${s.length} failure entries (${e.length} total)`,"",`**Voting agents (${o.length}):**`,...a.map(g=>{const S=g.vote==="success"?"\u2705":g.vote==="failure"?"\u274C":"\u2B1C",$="\u2593".repeat(Math.min(g.coverage,5))+"\u2591".repeat(Math.max(0,5-g.coverage));return` ${S} **${g.agent}** [${$}] ${g.coverage} CKG edges \u2014 ${g.reason}`}),"",w,""];return p==="unanimous_success"?C.push(`\u{1F527} Failure entries superseded \u2014 store confirmed lesson: \`learn_from_attempts(topic="${i}", outcome="success", ...)\``):p==="unanimous_failure"?C.push(`\u{1F6AB} Success claims unconfirmed \u2014 re-verify: \`recall_best_solution(topic="${i}")\``):C.push(`\u26A0\uFE0F Contested \u2014 run \`causal_trace\` before acting. Explore: \`ckg_inspect(concept="${k(i)}")\``),C.push("",`\u{1F4DD} Resolution node: \`cachly:ckg:node:${y}\``),C.join(`
4
4
  `)}case"cls_ingest":{const{instance_id:_,source:i,payload:n}=N,t=await I(_),e=new Date().toISOString(),l="cachly:cls:events";if(i==="git_commit"){const u=String(n.message??""),c=String(n.sha??""),o=Array.isArray(n.files)?n.files:[],d=/^fix/i.test(u)?"fix":/^feat/i.test(u)?"feat":/^refactor/i.test(u)?"refactor":/^test/i.test(u)?"test":"commit",h=`${d}:${k(u.slice(0,60))}`,s=k(h);await J(t,s,d,"commit");for(const f of o.slice(0,10)){const m=f.includes("auth")?"auth":f.includes("api")?"api":f.includes("infra")?"infra":f.includes("web")?"web":"code",p=k(`file:${m}`);await J(t,p,"file",m),await T(t,s,"co-occurs",p,!0)}const a={topic:h,outcome:"success",what_worked:u,what_failed:"",context:`CLS/git: sha=${c}`,severity:"minor",file_paths:o.slice(0,10),commands:c?[`git show ${c}`]:[],tags:["cls","git"],depends_on:[],recall_count:0,ts:e,verified_at:e,confidence:.6,audit_trail:[{ts:e,action:"cls_git_commit"}],version:3};return await t.rpush(`cachly:lessons:${h}`,JSON.stringify(a)),await t.get(`cachly:lesson:best:${h}`)||await t.set(`cachly:lesson:best:${h}`,JSON.stringify(a)),await t.rpush(l,JSON.stringify({source:i,payload:{message:u,sha:c},ts:e})),await t.ltrim(l,-200,-1),["\u{1F4E8} **CLS Ingested: git_commit**","",`Commit \`${c.slice(0,8)||"?"}\`: ${u.slice(0,80)}`,`Concept: \`${s}\` (${d}) \xB7 Files: ${o.length}`,"",`\u{1F578}\uFE0F CKG: \`${s}\` + ${o.length} file edges \xB7 Lesson: \`${h}\``,`\u{1F4A1} Inspect: \`ckg_inspect(concept="${d}")\``].join(`
@@ -21,13 +21,13 @@ import{createHmac as oe}from"node:crypto";import{ckgSlug as k,extractProblemConc
21
21
  `)}case"compact_recover":{const{instance_id:_,focus:i=""}=N,n=await I(_),t=[`\u{1F501} **Compact Recovery Briefing**
22
22
  `];t.push(`> *Call this first after any context limit hit. Reconstructs where you left off.*
23
23
  `);const e=await n.get("cachly:crystal:latest");if(e){const s=A(e,null);if(s){t.push(`### \u{1F48E} Memory Crystal: ${s.label}`),t.push(`Compressed from ${s.session_count} sessions, ${s.lesson_count} lessons.`);const a=i?s.top_patterns.filter(r=>r.category.toLowerCase().includes(i.toLowerCase())||r.insight.toLowerCase().includes(i.toLowerCase())).slice(0,4):s.top_patterns.slice(0,4);for(const r of a)t.push(` \u2022 **${r.category}**: ${r.insight.slice(0,100)}`);t.push("")}}const l=await n.get("cachly:session:last");if(l){const s=A(l,null);s&&(t.push("### \u{1F550} Last Session"),s.focus&&t.push(`Focus: _${s.focus}_`),s.summary&&t.push(`Summary: ${s.summary.slice(0,300)}`),t.push(""))}const u=await n.get("cachly:session:handoff");if(u){const s=A(u,null);if(s){if(t.push("### \u{1F4CB} Handoff (from last window)"),s.context_summary&&t.push(`Context: ${s.context_summary.slice(0,200)}`),s.remaining_tasks?.length){t.push("Remaining tasks:");for(const a of s.remaining_tasks.slice(0,5))t.push(` \u2022 ${a}`)}s.instructions&&t.push(`\u26A0\uFE0F Instructions: ${s.instructions.slice(0,200)}`),s.blocked_on&&t.push(`\u{1F6A7} Blocked on: ${s.blocked_on}`),t.push("")}}const c=await n.get("cachly:ctx:wip-registry");if(c){const s=A(c,null);s?.content&&(t.push("### \u{1F527} WIP Registry"),t.push(s.content.slice(0,400)),t.push(""))}const o=[],d=n.scanStream({match:"cachly:roadmap:*",count:100});await new Promise((s,a)=>{d.on("data",r=>o.push(...r)),d.on("end",s),d.on("error",a)});const h=[];for(const s of o.slice(0,30)){const a=await n.get(s);if(a)try{const r=JSON.parse(a);(r.status==="in_progress"||r.status==="blocked")&&h.push({title:r.title??s,status:r.status,priority:r.priority})}catch{}}if(h.length>0){t.push("### \u{1F6A7} Open Items");for(const s of h.slice(0,5))t.push(` \u2022 [${s.status}] ${s.title}`);t.push("")}if(i){const s=[],a=n.scanStream({match:"cachly:lesson:best:*",count:200});await new Promise((f,m)=>{a.on("data",p=>s.push(...p)),a.on("end",f),a.on("error",m)});const r=[];for(const f of s){const m=await n.get(f);if(m)try{const p=JSON.parse(m);p.topic.toLowerCase().includes(i.toLowerCase())&&p.what_worked&&r.push({topic:p.topic,what_worked:p.what_worked})}catch{}}if(r.length>0){t.push(`### \u{1F4A1} Relevant Lessons for "${i}"`);for(const f of r.slice(0,4))t.push(` \u2022 **${f.topic}**: ${f.what_worked.slice(0,100)}`);t.push("")}}return t.length<=3&&t.push("_No brain data found. Start accumulating knowledge with `learn_from_attempts` and `session_start`._"),t.push("---","\u{1F9E0} Brain is ready. Continue your work \u2014 full context restored."),t.join(`
24
- `)}case"brain_from_git":{const _=Date.now(),{instance_id:i,repo_path:n=".",limit:t=100,branch:e="HEAD",since:l="",incremental:u=!0}=N,c=await I(i),{execSync:o}=await import("node:child_process"),{resolve:d}=await import("node:path"),h=d(n),s=Math.min(Number(t)||100,500);await we();try{try{o("git rev-parse --git-dir",{cwd:h,stdio:"pipe"})}catch{return`\u274C Not a git repository: \`${h}\`. Pass \`repo_path\` pointing to a git checkout.`}const a=`cachly:brain_from_git:last_sha:${Buffer.from(h).toString("base64").slice(0,32)}`;let r="",f=!1;u!==!1&&!l&&(r=await c.get(a)??"",f=!!r);const m=l?`--since="${l}"`:"",w=(f?`${r}..HEAD`:"")||e,y=`git log ${w} ${m} --pretty=format:"COMMIT|||%H|||%s|||%ad|||%an" --date=short --no-merges --name-only -n ${s}`;let j="";try{j=o(y,{cwd:h,encoding:"utf-8",stdio:"pipe"})}catch(O){return`\u274C git log failed: ${O.message}. Check \`repo_path\` and \`branch\`.`}const C=[];let g=null;for(const O of j.split(`
24
+ `)}case"brain_from_git":{const _=Date.now(),{instance_id:i,repo_path:n=".",limit:t=100,branch:e="HEAD",since:l="",incremental:u=!0}=N,c=await I(i),{execSync:o}=await import("node:child_process"),{resolve:d}=await import("node:path"),h=d(n),s=Math.min(Number(t)||100,500);await ye();try{try{o("git rev-parse --git-dir",{cwd:h,stdio:"pipe"})}catch{return`\u274C Not a git repository: \`${h}\`. Pass \`repo_path\` pointing to a git checkout.`}const a=`cachly:brain_from_git:last_sha:${Buffer.from(h).toString("base64").slice(0,32)}`;let r="",f=!1;u!==!1&&!l&&(r=await c.get(a)??"",f=!!r);const m=l?`--since="${l}"`:"",w=(f?`${r}..HEAD`:"")||e,y=`git log ${w} ${m} --pretty=format:"COMMIT|||%H|||%s|||%ad|||%an" --date=short --no-merges --name-only -n ${s}`;let j="";try{j=o(y,{cwd:h,encoding:"utf-8",stdio:"pipe"})}catch(O){return`\u274C git log failed: ${O.message}. Check \`repo_path\` and \`branch\`.`}const C=[];let g=null;for(const O of j.split(`
25
25
  `)){const b=O.trim();if(b.startsWith("COMMIT|||")){g&&C.push(g);const[,D,G,F,q]=b.split("|||");g={sha:(D??"").trim(),subject:(G??"").trim(),date:(F??"").trim(),author:(q??"").trim(),files:[]}}else if(b&&g){const D=re(b);D&&g.files.push(D)}}if(g&&C.push(g),C.length===0)return f?`\u2705 brain_from_git: Brain is up to date \u2014 no new commits since last run (last SHA: \`${r.slice(0,8)}\`).`:Z({repoDir:h,revRange:w,processed:0,ingested:0,skipped:0,durationMs:Date.now()-_,isIncremental:!1,instanceId:i,categories:[],suggestedQueries:[],emptyReason:`No commits found in \`${h}\` on branch \`${e}\`${l?` since ${l}`:""}.`});const S=new Date().toISOString();let $=0,x=0;const v=new Map,L=new Map,P=[];let R=null;const E=C.length,te=Math.max(1,Math.floor(E/10));let z=0;process.stderr.write(`
26
26
  \u{1F9E0} brain_from_git: processing ${E} commits from ${h}...
27
27
  `);for(let O=0;O<C.length;O++){const b=C[O];if(O-z>=te&&(process.stderr.write(` \u23F3 Processing ${O}/${E} commits (${$} lessons so far)...
28
- `),z=O),!b.subject){x++;continue}const{category:D,outcome:G,severity:F}=he(b.subject),q=me(b.subject),M=`${D}:${q}`;v.set(D,(v.get(D)??0)+1),L.set(F,(L.get(F)??0)+1),P.push(M),(!R||D==="fix"&&!R.topic.startsWith("fix:"))&&(R={topic:M,subject:b.subject});const Y=b.files.filter(H=>H.length>0).slice(0,12),V={topic:M,outcome:G,severity:F,what_worked:b.subject.slice(0,200),what_failed:"",context:`git:${b.sha.slice(0,8)} by ${b.author} on ${b.date}`,author:b.author||void 0,file_paths:Y,commands:[`git show ${b.sha.slice(0,8)}`],tags:["brain_from_git",D,"git-history"],visibility:"team",depends_on:[],recall_count:0,ts:S,verified_at:S,confidence:.55,audit_trail:[{ts:S,action:"brain_from_git",sha:b.sha.slice(0,8)}],version:3};await c.get(`cachly:lesson:best:${M}`)||(await c.set(`cachly:lesson:best:${M}`,JSON.stringify(V),"EX",90*86400),await c.rpush(`cachly:lessons:${M}`,JSON.stringify(V)),await c.ltrim(`cachly:lessons:${M}`,-100,-1),await c.expire(`cachly:lessons:${M}`,90*86400)),await c.rpush("cachly:lessons:brain_from_git:all",JSON.stringify({topic:M,sha:b.sha.slice(0,8),subject:b.subject.slice(0,60)})),await c.ltrim("cachly:lessons:brain_from_git:all",-500,-1),await c.expire("cachly:lessons:brain_from_git:all",90*86400);const Q=k(M);if(await J(c,Q,D,"git-derived"),b.author)try{const H=await ie(c,b.author,D);await T(c,H,"authored",Q,G==="success",G==="partial");for(const se of Y.slice(0,8)){const X=await ae(c,se);await T(c,H,"touched",X,!0),await ce(c,X,H)}}catch{}$++}process.stderr.write(` \u2705 brain_from_git complete: ${$}/${E} commits ingested
28
+ `),z=O),!b.subject){x++;continue}const{category:D,outcome:G,severity:F}=me(b.subject),q=pe(b.subject),M=`${D}:${q}`;v.set(D,(v.get(D)??0)+1),L.set(F,(L.get(F)??0)+1),P.push(M),(!R||D==="fix"&&!R.topic.startsWith("fix:"))&&(R={topic:M,subject:b.subject});const Y=b.files.filter(H=>H.length>0).slice(0,12),V={topic:M,outcome:G,severity:F,what_worked:b.subject.slice(0,200),what_failed:"",context:`git:${b.sha.slice(0,8)} by ${b.author} on ${b.date}`,author:b.author||void 0,file_paths:Y,commands:[`git show ${b.sha.slice(0,8)}`],tags:["brain_from_git",D,"git-history"],visibility:"team",depends_on:[],recall_count:0,ts:S,verified_at:S,confidence:.55,audit_trail:[{ts:S,action:"brain_from_git",sha:b.sha.slice(0,8)}],version:3};await c.get(`cachly:lesson:best:${M}`)||(await c.set(`cachly:lesson:best:${M}`,JSON.stringify(V),"EX",90*86400),await c.rpush(`cachly:lessons:${M}`,JSON.stringify(V)),await c.ltrim(`cachly:lessons:${M}`,-100,-1),await c.expire(`cachly:lessons:${M}`,90*86400)),await c.rpush("cachly:lessons:brain_from_git:all",JSON.stringify({topic:M,sha:b.sha.slice(0,8),subject:b.subject.slice(0,60)})),await c.ltrim("cachly:lessons:brain_from_git:all",-500,-1),await c.expire("cachly:lessons:brain_from_git:all",90*86400);const Q=k(M);if(await J(c,Q,D,"git-derived"),b.author)try{const H=await ie(c,b.author,D);await T(c,H,"authored",Q,G==="success",G==="partial");for(const se of Y.slice(0,8)){const X=await ae(c,se);await T(c,H,"touched",X,!0),await ce(c,X,H)}}catch{}$++}process.stderr.write(` \u2705 brain_from_git complete: ${$}/${E} commits ingested
29
29
 
30
- `),C.length>0&&C[0]?.sha&&await c.set(a,C[0].sha,"EX",2160*3600),pe={fixes:v.get("fix")??0,features:v.get("feat")??0,refactors:v.get("refactor")??0,total:$};let W=null;if(R&&$>0)try{const O=await de(c,["cachly:lesson:best:*"],R.subject,1);if(O.length>0){const b=A(O[0].content,{});W={query:R.subject.slice(0,80),topic:b.topic??O[0].key.replace("cachly:lesson:best:",""),snippet:(b.what_worked??"").slice(0,120)||R.subject.slice(0,120)}}}catch{}return Z({repoDir:h,revRange:w,processed:C.length,ingested:$,skipped:x,durationMs:Date.now()-_,isIncremental:f,lastSha:r,instanceId:i,categories:[...v.entries()].sort((O,b)=>b[1]-O[1]),severities:[...L.entries()].sort((O,b)=>b[1]-O[1]),proof:W,suggestedQueries:fe(P,i)})}finally{ye()}}case"brain_from_ci":{const{instance_id:_,outcomes:i}=N,n=await I(_),t=Date.now();let e=0,l=0,u=0;const c=i.length;for(const o of i){const d=String(o.status??""),h=String(o.prev_status??""),s=String(o.job??"unknown"),a=String(o.context??""),r=["failure","red","error"].includes(h)&&["success","green","passed"].includes(d),f=["success","green","passed"].includes(h)&&["failure","red","error"].includes(d),m=`ci:${k(s)}`,p=k(m);if(await J(n,p,"ci","job"),r){const y=k(`problem:${k(s)}`);await J(n,y,"problem","ci-failure"),await T(n,p,"fixes",y,!0);const j={topic:m,outcome:"success",what_worked:`CI job "${s}" went ${h} \u2192 ${d}`,what_failed:`Job "${s}" was failing`,context:`brain_from_ci: ${a}`,severity:"major",file_paths:[],commands:[],tags:["brain_from_ci","ci"],depends_on:[],recall_count:0,ts:t,verified_at:t,confidence:.65,audit_trail:[{ts:t,action:"brain_from_ci_fixed"}],version:3};await n.rpush(`cachly:lessons:${m}`,JSON.stringify(j)),await n.ltrim(`cachly:lessons:${m}`,-100,-1),await n.set(`cachly:lesson:best:${m}`,JSON.stringify(j)),e++}else if(f){const y=k(`cause:${k(s)}`);await J(n,y,"cause","ci-break"),await T(n,p,"causes",y,!1),l++}else u++;const w=`cachly:cls:${_}`;await n.rpush(w,JSON.stringify({source:"ci_outcome",payload:{status:d,prev_status:h,job:s},ts:t})),await n.ltrim(w,-200,-1)}return ge={fixes:e,breaks:l,stable:u,total:c},[`\u{1F4E5} **brain_from_ci**: Ingested ${c} outcomes \u2014 ${e} fixes learned, ${l} breaks noted, ${u} stable`,"",e>0?`\u2705 ${e} fix lesson${e!==1?"s":""} written (confidence 0.65) \u2014 CKG \`fixes\` edges added`:"",l>0?`\u{1F534} ${l} break${l!==1?"s":""} noted \u2014 CKG \`causes\` edges added`:"",u>0?`\u{1F4CA} ${u} stable outcome${u!==1?"s":""} recorded`:"","",'\u{1F4A1} Explore: `brain_search(query="ci")` | `brain_predict(context="<job-name>")`'].filter(Boolean).join(`
30
+ `),$>0&&fe(),C.length>0&&C[0]?.sha&&await c.set(a,C[0].sha,"EX",2160*3600),ge={fixes:v.get("fix")??0,features:v.get("feat")??0,refactors:v.get("refactor")??0,total:$};let W=null;if(R&&$>0)try{const O=await de(c,["cachly:lesson:best:*"],R.subject,1);if(O.length>0){const b=A(O[0].content,{});W={query:R.subject.slice(0,80),topic:b.topic??O[0].key.replace("cachly:lesson:best:",""),snippet:(b.what_worked??"").slice(0,120)||R.subject.slice(0,120)}}}catch{}return Z({repoDir:h,revRange:w,processed:C.length,ingested:$,skipped:x,durationMs:Date.now()-_,isIncremental:f,lastSha:r,instanceId:i,categories:[...v.entries()].sort((O,b)=>b[1]-O[1]),severities:[...L.entries()].sort((O,b)=>b[1]-O[1]),proof:W,suggestedQueries:he(P,i)})}finally{$e()}}case"brain_from_ci":{const{instance_id:_,outcomes:i}=N,n=await I(_),t=Date.now();let e=0,l=0,u=0;const c=i.length;for(const o of i){const d=String(o.status??""),h=String(o.prev_status??""),s=String(o.job??"unknown"),a=String(o.context??""),r=["failure","red","error"].includes(h)&&["success","green","passed"].includes(d),f=["success","green","passed"].includes(h)&&["failure","red","error"].includes(d),m=`ci:${k(s)}`,p=k(m);if(await J(n,p,"ci","job"),r){const y=k(`problem:${k(s)}`);await J(n,y,"problem","ci-failure"),await T(n,p,"fixes",y,!0);const j={topic:m,outcome:"success",what_worked:`CI job "${s}" went ${h} \u2192 ${d}`,what_failed:`Job "${s}" was failing`,context:`brain_from_ci: ${a}`,severity:"major",file_paths:[],commands:[],tags:["brain_from_ci","ci"],depends_on:[],recall_count:0,ts:t,verified_at:t,confidence:.65,audit_trail:[{ts:t,action:"brain_from_ci_fixed"}],version:3};await n.rpush(`cachly:lessons:${m}`,JSON.stringify(j)),await n.ltrim(`cachly:lessons:${m}`,-100,-1),await n.set(`cachly:lesson:best:${m}`,JSON.stringify(j)),e++}else if(f){const y=k(`cause:${k(s)}`);await J(n,y,"cause","ci-break"),await T(n,p,"causes",y,!1),l++}else u++;const w=`cachly:cls:${_}`;await n.rpush(w,JSON.stringify({source:"ci_outcome",payload:{status:d,prev_status:h,job:s},ts:t})),await n.ltrim(w,-200,-1)}return _e={fixes:e,breaks:l,stable:u,total:c},[`\u{1F4E5} **brain_from_ci**: Ingested ${c} outcomes \u2014 ${e} fixes learned, ${l} breaks noted, ${u} stable`,"",e>0?`\u2705 ${e} fix lesson${e!==1?"s":""} written (confidence 0.65) \u2014 CKG \`fixes\` edges added`:"",l>0?`\u{1F534} ${l} break${l!==1?"s":""} noted \u2014 CKG \`causes\` edges added`:"",u>0?`\u{1F4CA} ${u} stable outcome${u!==1?"s":""} recorded`:"","",'\u{1F4A1} Explore: `brain_search(query="ci")` | `brain_predict(context="<job-name>")`'].filter(Boolean).join(`
31
31
  `)}case"brain_predict_failures":{const{instance_id:_,context:i,top_k:n=5,format:t="detailed"}=N,e=await I(_),l=i.toLowerCase().replace(/[^a-z0-9\s\-_:.]/g," ").split(/\s+/).filter(r=>r.length>2),u=[];for(const r of l.slice(0,8)){const f=[],m=e.scanStream({match:`cachly:ckg:node:*${r}*`,count:50});await new Promise((p,w)=>{m.on("data",y=>f.push(...y)),m.on("end",p),m.on("error",w)});for(const p of f.slice(0,5)){const w=await e.get(p);if(!w)continue;const y=A(w,null);if(!y)continue;const j=await e.smembers(`cachly:ckg:idx:from:${y.id}`);for(const C of j.slice(0,20)){const g=await e.get(C);if(!g)continue;const S=A(g,null);if(!S||S.edgeType!=="causes"&&S.edgeType!=="degrades_under")continue;const $=await e.smembers(`cachly:ckg:idx:from:${S.to}`);let x;for(const v of $.slice(0,10)){const L=await e.get(v);if(!L)continue;const P=A(L,null);if(P&&P.edgeType==="fixes"){const R=await e.get(`cachly:lesson:best:${P.from}`);if(R){x=A(R,null)?.what_worked?.slice(0,120);break}}}u.push({concept:y.id,failure:S.to.replace(/-/g," "),probability:S.confidence,fix:x,source:"ckg"})}}}const c=[],o=e.scanStream({match:"cachly:lesson:best:*",count:300});await new Promise((r,f)=>{o.on("data",m=>c.push(...m)),o.on("end",r),o.on("error",f)});for(const r of c.slice(0,100)){const f=await e.get(r);if(f)try{const m=JSON.parse(f);if(m.outcome!=="failure"&&m.outcome!=="partial"||!m.what_failed)continue;const p=`${m.topic} ${m.what_failed}`.toLowerCase(),w=l.filter(j=>p.includes(j)).length/Math.max(1,l.length);if(w<.15)continue;const y=m.severity==="critical"?.15:m.severity==="major"?.05:0;u.push({concept:m.topic,failure:m.what_failed.slice(0,80),probability:Math.min(.97,(m.confidence??.5)*w*1.5+y),fix:m.what_worked?.slice(0,120),topic:m.topic,source:"lesson"})}catch{}}if(u.length===0)return[`\u{1F52E} **Failure Prediction: "${i}"**`,"","No known failure patterns found for this context.",'\u{1F4A1} The brain learns from every `learn_from_attempts(outcome="failure")` call.',`\u{1F50D} Try: \`brain_predict(context="${i}")\` for broader predictions.`].join(`
32
32
  `);const d=new Set,h=u.filter(r=>{const f=r.failure.slice(0,40);return d.has(f)?!1:(d.add(f),!0)}).sort((r,f)=>f.probability-r.probability).slice(0,Number(n)),s=[`\u{1F52E} **Failure Prediction for: "${i}"**
33
33
  `];s.push(`> Pre-deploy failure analysis based on ${u.length} patterns. Ranked by probability.
@@ -37,4 +37,4 @@ import{createHmac as oe}from"node:crypto";import{ckgSlug as k,extractProblemConc
37
37
  `);const l=await I(_);let u=0;for(const o of t){const d=`cachly:lesson:best:meta:${o.topic_category}`;await l.get(d)||(await l.set(d,JSON.stringify({topic:`meta:${o.topic_category}`,outcome:o.dominant_outcome,what_worked:o.contributor_count!=null?`Meta-pattern from ${o.contributor_count} independent orgs`:`Meta-pattern from ${o.signal_count} signals`,what_failed:"",recall_count:0,ts:o.derived_at,state:"meta",avg_confidence:o.avg_confidence,signal_count:o.signal_count,audit_trail:[{ts:new Date().toISOString(),action:"imported_meta"}]})),u++)}const c=[`\u{1F310} **Brain Import Meta-Lessons** (k \u2265 ${e})`,"","| Topic Category | Outcome | Confidence | Signals |","|---|---|---|---|"];for(const o of t.slice(0,15)){const d=(o.avg_confidence*100).toFixed(0)+"%";c.push(`| \`${o.topic_category}\` | ${o.dominant_outcome} | ${d} | ${o.signal_count} |`)}return t.length>15&&c.push(`| _\u2026${t.length-15} more_ | | | |`),c.push("",`\u2705 **${u}** new meta-lessons imported into local Brain.`),u<t.length&&c.push(`_(${t.length-u} already present \u2014 not overwritten)_`),c.join(`
38
38
  `)}case"brain_watch":{const{instance_id:_="",project_dir:i=".",api_key:n}=N,{resolve:t}=await import("node:path"),e=t(i),{result:l,hookPath:u}=await ue(e,_,n);return l==="skipped-no-git"?["\u26A0\uFE0F **brain_watch: no git repository found**","",`No \`.git\` directory in \`${e}\`.`,"Pass `project_dir` pointing to a git checkout."].join(`
39
39
  `):[`\u{1F9E0} **brain_watch ${{written:"\u2705 Hook installed (new)",upgraded:"\u{1F504} Hook upgraded to latest version",appended:"\u{1F4CE} Hook appended to existing post-commit script",unchanged:"\u2713 Hook already up to date \u2014 nothing changed"}[l]??l}**`,"",`Hook path: \`${u}\``,`Instance: \`${_||"(none \u2014 set CACHLY_BRAIN_INSTANCE_ID or pass instance_id)"}\``,"","Every future commit will automatically teach your Brain.","No manual `brain_from_git` needed \u2014 the hook runs silently in the background.","",'\u{1F4A1} Verify: `git commit --allow-empty -m "test brain_watch"` then `smart_recall(query="test")`'].join(`
40
- `)}default:return null}}export{Ne as FEDBRAIN_TOOL_NAMES,ge as _lastBrainFromCiCounts,pe as _lastBrainFromGitCounts,Ie as handleFedbrainTool};
40
+ `)}default:return null}}export{Ie as FEDBRAIN_TOOL_NAMES,_e as _lastBrainFromCiCounts,ge as _lastBrainFromGitCounts,Le as handleFedbrainTool};
@@ -1,19 +1,19 @@
1
- import{safeJsonParse as T}from"../utils.js";import{STARTER_CORPUS as k,STARTER_CORPUS_SIZE as x}from"../starter-corpus.js";import{cachlyUrl as j}from"../cachly-url.js";const E=new Set(["brain_share","brain_import","brain_share_list","brain_unshare","brain_discover","brain_seed_starter"]);async function R(v,w){const y=[],$=v.scanStream({match:"cachly:lesson:best:*",count:200});await new Promise((s,h)=>{$.on("data",e=>y.push(...e)),$.on("end",s),$.on("error",h)});const o=[];for(const s of y.slice(0,500)){const h=await v.get(s);if(!h)continue;const e=T(h,null);!e||!e.topic||w&&w.length>0&&!w.some(a=>e.topic.includes(a))||o.push({topic:e.topic,outcome:e.outcome,...e.what_worked?{what_worked:e.what_worked}:{},...e.what_failed?{what_failed:e.what_failed}:{},...e.ctx?{ctx:e.ctx}:{},...e.tags?.length?{tags:e.tags}:{},...e.author?{author:e.author}:{},...e.service?{service:e.service}:{},confidence:e.confidence??1,ts:e.ts})}return o}async function A(v,w,y,$){switch(v){case"brain_share":{const{instance_id:o,title:s="My Brain Snapshot",description:h="",topic_filter:e,visibility:t="unlisted",max_lessons:a=100,dry_run:r=!1}=w;if(!o)return"\u26A0\uFE0F `brain_share` requires `instance_id`.";const l=await y(o),c=Array.isArray(e)&&e.length>0?e:void 0,i=(await R(l,c)).slice(0,a);if(i.length===0)return["\u{1F4E4} **brain_share** \u2014 nothing to share yet","",`No lessons found in Brain \`${o}\`${c?` matching topics: ${c.join(", ")}`:""}.`,"",'Store lessons first with `learn_from_attempts(topic="...", what_worked="...")`.'].join(`
1
+ import{safeJsonParse as j}from"../utils.js";import{STARTER_CORPUS as k,STARTER_CORPUS_SIZE as x}from"../starter-corpus.js";import{cachlyUrl as T}from"../cachly-url.js";import{VEKTOR_NACHTRAG as R}from"../bedeutung.js";const q=new Set(["brain_share","brain_import","brain_share_list","brain_unshare","brain_discover","brain_seed_starter"]);async function I(v,w){const y=[],$=v.scanStream({match:"cachly:lesson:best:*",count:200});await new Promise((s,h)=>{$.on("data",e=>y.push(...e)),$.on("end",s),$.on("error",h)});const o=[];for(const s of y.slice(0,500)){const h=await v.get(s);if(!h)continue;const e=j(h,null);!e||!e.topic||w&&w.length>0&&!w.some(a=>e.topic.includes(a))||o.push({topic:e.topic,outcome:e.outcome,...e.what_worked?{what_worked:e.what_worked}:{},...e.what_failed?{what_failed:e.what_failed}:{},...e.ctx?{ctx:e.ctx}:{},...e.tags?.length?{tags:e.tags}:{},...e.author?{author:e.author}:{},...e.service?{service:e.service}:{},confidence:e.confidence??1,ts:e.ts})}return o}async function J(v,w,y,$){switch(v){case"brain_share":{const{instance_id:o,title:s="My Brain Snapshot",description:h="",topic_filter:e,visibility:t="unlisted",max_lessons:a=100,dry_run:r=!1}=w;if(!o)return"\u26A0\uFE0F `brain_share` requires `instance_id`.";const l=await y(o),c=Array.isArray(e)&&e.length>0?e:void 0,i=(await I(l,c)).slice(0,a);if(i.length===0)return["\u{1F4E4} **brain_share** \u2014 nothing to share yet","",`No lessons found in Brain \`${o}\`${c?` matching topics: ${c.join(", ")}`:""}.`,"",'Store lessons first with `learn_from_attempts(topic="...", what_worked="...")`.'].join(`
2
2
  `);if(r){const u=i.slice(0,5).map(p=>` ${p.outcome==="success"?"\u2705":p.outcome==="failure"?"\u274C":"\u26A0\uFE0F"} \`${p.topic}\` \u2014 ${(p.what_worked??p.what_failed??"").slice(0,80)}`);return[`\u{1F4E4} **brain_share (DRY RUN)** \u2014 would share ${i.length} lesson${i.length!==1?"s":""}`,"",`**Title:** ${s}`,`**Visibility:** ${t}`,c?`**Topic filter:** ${c.join(", ")}`:"","","**Sample lessons (first 5):**",...u,i.length>5?` _...and ${i.length-5} more_`:"","","_Remove `dry_run=true` to create the public share._"].filter(p=>p!=="").join(`
3
- `)}let n=null,d=null;try{n=(await $("/api/v1/brains/share",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:s,description:h,visibility:t,lessons:i})})).share_id??null,n&&(d=j(`/brain/share/${n}`,"brain-share"))}catch(u){const p=u.message??"";if(p.includes("404")||p.includes("not found")||p.includes("ECONNREFUSED")){const f=JSON.stringify({title:s,description:h,visibility:t,lessons:i,exported_at:new Date().toISOString()},null,2);return[`\u{1F4E4} **brain_share** \u2014 exported ${i.length} lesson${i.length!==1?"s":""}`,"","\u26A0\uFE0F The public share API is not yet available. Here is your portable snapshot:","","```json",f.slice(0,3e3)+(f.length>3e3?`
3
+ `)}let n=null,d=null;try{n=(await $("/api/v1/brains/share",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({title:s,description:h,visibility:t,lessons:i})})).share_id??null,n&&(d=T(`/brain/share/${n}`,"brain-share"))}catch(u){const p=u.message??"";if(p.includes("404")||p.includes("not found")||p.includes("ECONNREFUSED")){const m=JSON.stringify({title:s,description:h,visibility:t,lessons:i,exported_at:new Date().toISOString()},null,2);return[`\u{1F4E4} **brain_share** \u2014 exported ${i.length} lesson${i.length!==1?"s":""}`,"","\u26A0\uFE0F The public share API is not yet available. Here is your portable snapshot:","","```json",m.slice(0,3e3)+(m.length>3e3?`
4
4
  ... (truncated)`:""),"```","","_To import this on another Brain, use `brain_import` with the JSON payload._"].join(`
5
5
  `)}return`\u274C brain_share failed: ${u.message}`}const b=i.slice(0,5).map(u=>` ${u.outcome==="success"?"\u2705":u.outcome==="failure"?"\u274C":"\u26A0\uFE0F"} \`${u.topic}\``);try{const u=JSON.stringify({share_id:n,title:s,visibility:t,lesson_count:i.length,created_at:new Date().toISOString()});await l.rpush("cachly:brain:shares",u),await l.ltrim("cachly:brain:shares",-20,-1)}catch{}return[`\u{1F4E4} **brain_share** \u2014 ${i.length} lesson${i.length!==1?"s":""} shared`,"",`**Share ID:** \`${n}\``,`**URL:** ${d}`,`**Title:** ${s}`,`**Visible:** ${t}`,"","**Sample lessons:**",...b,i.length>5?` _...and ${i.length-5} more_`:"","","**Anyone can import this Brain with:**",`\`brain_import(instance_id="<their-id>", share_id="${n}")\``,"","_To list all your shares, run `brain_share_list`._"].filter(u=>u!=="").join(`
6
- `)}case"brain_import":{const{instance_id:o,share_id:s,topic_prefix:h="",min_confidence:e=0,dry_run:t=!1,overwrite:a=!1}=w;if(!o)return"\u26A0\uFE0F `brain_import` requires `instance_id`.";if(!s)return"\u26A0\uFE0F `brain_import` requires `share_id`. Get one from `brain_share`.";const r=s.replace(/^.*\/brain\/share\//,"").trim();let l;try{l=await $(`/api/v1/brains/share/${r}`)}catch(m){const g=m.message??"";return g.includes("404")||g.includes("not found")?["\u274C **brain_import** \u2014 share not found","",`Share ID \`${r}\` does not exist or has been removed.`,"","Ask the Brain owner to re-run `brain_share` and share the new ID with you."].join(`
7
- `):`\u274C brain_import failed: ${m.message}`}const c=l.lessons??[];if(c.length===0)return`\u26A0\uFE0F Share \`${r}\` exists but contains no lessons.`;const _=await y(o);let i=0,n=0,d=0;const b=[];for(const m of c){if((m.confidence??1)<e){n++;continue}const g=h?`${h}:${m.topic}`:m.topic,N=`cachly:lesson:best:${g}`;if(!a&&await _.get(N)){d++;continue}const O=JSON.stringify({...m,topic:g,imported_from:r,imported_at:new Date().toISOString()});if(!t){await _.set(N,O);const S=`cachly:lessons:${g}`;await _.rpush(S,O),await _.ltrim(S,-100,-1),await _.expire(S,90*86400)}if(i++,b.length<6){const S=m.outcome==="success"?"\u2705":m.outcome==="failure"?"\u274C":"\u26A0\uFE0F";b.push(` ${S} \`${g}\` \u2014 ${(m.what_worked??m.what_failed??"").slice(0,80)}`)}}if(!t&&i>0)try{const m=JSON.stringify({share_id:r,title:l.title,imported:i,skipped:n,conflicts:d,topic_prefix:h,imported_at:new Date().toISOString()});await _.rpush("cachly:brain:imports",m),await _.ltrim("cachly:brain:imports",-20,-1)}catch{}const u=t?" (DRY RUN \u2014 no writes)":"",p=l.title??r,f=[`\u{1F4E5} **brain_import${u}** \u2014 from "${p}"`,"",`**Share ID:** \`${r}\``,`**Lessons imported:** ${i}`,...n>0?[`**Skipped (low confidence):** ${n}`]:[],...d>0?[`**Skipped (already exist):** ${d} _(pass \`overwrite=true\` to replace)_`]:[],""];return b.length>0&&(f.push("**Sample lessons imported:**",...b),i>6&&f.push(` _...and ${i-6} more_`)),i>0&&!t?f.push("",'\u2705 Brain updated \u2014 use `smart_recall(query="...")` to query the new knowledge.'):t?f.push("","_Remove `dry_run=true` to actually import these lessons._"):i===0&&d>0&&f.push("","\u2139\uFE0F All lessons already exist in your Brain. Pass `overwrite=true` to update them."),f.join(`
6
+ `)}case"brain_import":{const{instance_id:o,share_id:s,topic_prefix:h="",min_confidence:e=0,dry_run:t=!1,overwrite:a=!1}=w;if(!o)return"\u26A0\uFE0F `brain_import` requires `instance_id`.";if(!s)return"\u26A0\uFE0F `brain_import` requires `share_id`. Get one from `brain_share`.";const r=s.replace(/^.*\/brain\/share\//,"").trim();let l;try{l=await $(`/api/v1/brains/share/${r}`)}catch(f){const g=f.message??"";return g.includes("404")||g.includes("not found")?["\u274C **brain_import** \u2014 share not found","",`Share ID \`${r}\` does not exist or has been removed.`,"","Ask the Brain owner to re-run `brain_share` and share the new ID with you."].join(`
7
+ `):`\u274C brain_import failed: ${f.message}`}const c=l.lessons??[];if(c.length===0)return`\u26A0\uFE0F Share \`${r}\` exists but contains no lessons.`;const _=await y(o);let i=0,n=0,d=0;const b=[];for(const f of c){if((f.confidence??1)<e){n++;continue}const g=h?`${h}:${f.topic}`:f.topic,N=`cachly:lesson:best:${g}`;if(!a&&await _.get(N)){d++;continue}const O=JSON.stringify({...f,topic:g,imported_from:r,imported_at:new Date().toISOString()});if(!t){await _.set(N,O);const S=`cachly:lessons:${g}`;await _.rpush(S,O),await _.ltrim(S,-100,-1),await _.expire(S,90*86400)}if(i++,b.length<6){const S=f.outcome==="success"?"\u2705":f.outcome==="failure"?"\u274C":"\u26A0\uFE0F";b.push(` ${S} \`${g}\` \u2014 ${(f.what_worked??f.what_failed??"").slice(0,80)}`)}}if(!t&&i>0)try{const f=JSON.stringify({share_id:r,title:l.title,imported:i,skipped:n,conflicts:d,topic_prefix:h,imported_at:new Date().toISOString()});await _.rpush("cachly:brain:imports",f),await _.ltrim("cachly:brain:imports",-20,-1)}catch{}const u=t?" (DRY RUN \u2014 no writes)":"",p=l.title??r,m=[`\u{1F4E5} **brain_import${u}** \u2014 from "${p}"`,"",`**Share ID:** \`${r}\``,`**Lessons imported:** ${i}`,...n>0?[`**Skipped (low confidence):** ${n}`]:[],...d>0?[`**Skipped (already exist):** ${d} _(pass \`overwrite=true\` to replace)_`]:[],""];return b.length>0&&(m.push("**Sample lessons imported:**",...b),i>6&&m.push(` _...and ${i-6} more_`)),i>0&&!t?m.push("",'\u2705 Brain updated \u2014 use `smart_recall(query="...")` to query the new knowledge.'):t?m.push("","_Remove `dry_run=true` to actually import these lessons._"):i===0&&d>0&&m.push("","\u2139\uFE0F All lessons already exist in your Brain. Pass `overwrite=true` to update them."),m.join(`
8
8
  `)}case"brain_share_list":{const{instance_id:o}=w;if(!o)return"\u26A0\uFE0F `brain_share_list` requires `instance_id`.";const s=await y(o);let h=[];try{h=(await s.lrange("cachly:brain:shares",0,-1)).map(c=>{try{return JSON.parse(c)}catch{return null}}).filter(Boolean)}catch{}let e=[];try{e=(await $("/api/v1/brains/share")).shares??[]}catch{}const t=e.length>0?e:h;if(t.length===0)return["\u{1F4E4} **brain_share_list** \u2014 no shares yet","","You haven't shared any Brain snapshots from this instance.","",`Create one with: \`brain_share(instance_id="${o}", title="My Patterns")\``].join(`
9
9
  `);const a=[`\u{1F4E4} **Your Brain Shares** (${t.length})`,"","| # | Title | Lessons | Visibility | Created |","|---|-------|---------|------------|---------|"];for(const[l,c]of t.entries()){const _=new Date(c.created_at),i=isNaN(_.getTime())?c.created_at:_.toISOString().slice(0,10),n=c.visibility==="public"?"\u{1F310} public":"\u{1F517} unlisted";a.push(`| ${l+1} | ${c.title??"\u2014"} | ${c.lesson_count??"?"} | ${n} | ${i} |`)}const r=t[t.length-1];return a.push("",`**Import command:** \`brain_import(instance_id="<their-id>", share_id="${r?.share_id??"..."}")\``,`**Revoke:** \`brain_unshare(instance_id="${o}", share_id="<id>")\``),a.join(`
10
10
  `)}case"brain_unshare":{const{instance_id:o,share_id:s}=w;if(!o)return"\u26A0\uFE0F `brain_unshare` requires `instance_id`.";if(!s)return"\u26A0\uFE0F `brain_unshare` requires `share_id`.";try{await $(`/api/v1/brains/share/${s}`,{method:"DELETE"})}catch(e){const t=e.message??"";if(t.includes("404")||t.includes("not found"))return`\u274C Share \`${s}\` not found \u2014 it may have already been removed.`;if(t.includes("ECONNREFUSED")||t.includes("fetch failed")){const a=await y(o);try{const l=(await a.lrange("cachly:brain:shares",0,-1)).filter(c=>{try{return JSON.parse(c).share_id!==s}catch{return!0}});await a.del("cachly:brain:shares");for(const c of l)await a.rpush("cachly:brain:shares",c)}catch{}return["\u26A0\uFE0F **brain_unshare** \u2014 removed from local log","",`API unreachable \u2014 removed \`${s}\` from your local share registry.`,"The public link may still be accessible until the API confirms deletion."].join(`
11
11
  `)}return`\u274C brain_unshare failed: ${t}`}const h=await y(o);try{const t=(await h.lrange("cachly:brain:shares",0,-1)).filter(a=>{try{return JSON.parse(a).share_id!==s}catch{return!0}});await h.del("cachly:brain:shares");for(const a of t)await h.rpush("cachly:brain:shares",a)}catch{}return["\u{1F5D1}\uFE0F **brain_unshare** \u2014 share revoked","",`Share \`${s}\` has been deleted. The public link is no longer accessible.`,"","_Anyone who already imported this Brain keeps their local copy._"].join(`
12
- `)}case"brain_discover":{const{query:o="",topic:s="",limit:h=10}=w;let e=[];try{const a=new URLSearchParams;o&&a.set("q",o),s&&a.set("topic",s),a.set("limit",String(h)),e=await $(`/api/v1/brains/discover?${a.toString()}`)}catch(a){const r=a.message??"";return r.includes("404")||r.includes("ECONNREFUSED")||r.includes("fetch failed")?["\u{1F50D} **brain_discover** \u2014 marketplace not yet live","","The public Brain marketplace is coming soon.","","**In the meantime:**",' \u2022 Share your Brain: `brain_share(instance_id="...", visibility="public")`',' \u2022 Import by ID: `brain_import(instance_id="...", share_id="<id>")`',` \u2022 Community index: ${j("/brains","brain-discover")}`].join(`
12
+ `)}case"brain_discover":{const{query:o="",topic:s="",limit:h=10}=w;let e=[];try{const a=new URLSearchParams;o&&a.set("q",o),s&&a.set("topic",s),a.set("limit",String(h)),e=await $(`/api/v1/brains/discover?${a.toString()}`)}catch(a){const r=a.message??"";return r.includes("404")||r.includes("ECONNREFUSED")||r.includes("fetch failed")?["\u{1F50D} **brain_discover** \u2014 marketplace not yet live","","The public Brain marketplace is coming soon.","","**In the meantime:**",' \u2022 Share your Brain: `brain_share(instance_id="...", visibility="public")`',' \u2022 Import by ID: `brain_import(instance_id="...", share_id="<id>")`',` \u2022 Community index: ${T("/brains","brain-discover")}`].join(`
13
13
  `):`\u274C brain_discover failed: ${r}`}if(e.length===0)return[`\u{1F50D} **brain_discover** \u2014 no public Brains found ${o?`matching "${o}"`:s?`in topic "${s}"`:""}`.trim(),"",'Be the first! `brain_share(instance_id="...", visibility="public")`'].join(`
14
- `);const t=[`\u{1F50D} **brain_discover**${o?` \u2014 "${o}"`:""}${s?` \xB7 topic: ${s}`:""} (${e.length} result${e.length!==1?"s":""})`,""];for(const[a,r]of e.entries()){const l=new Date(r.created_at),c=isNaN(l.getTime())?"":` \xB7 ${l.toISOString().slice(0,10)}`,_=r.imports!=null?` \xB7 ${r.imports} imports`:"",i=r.topics?.length?` \xB7 topics: ${r.topics.slice(0,4).join(", ")}`:"",n=r.author?` by **${r.author}**`:"";t.push(`**${a+1}. ${r.title}**${n}`,` \u{1F4DA} ${r.lesson_count} lessons${i}${_}${c}`,r.description?` _${r.description.slice(0,120)}_`:"",` \`brain_import(instance_id="...", share_id="${r.share_id}")\``,"")}return t.push(`_Browse more at ${j("/brains","brain-discover")}_`),t.filter(a=>a!==" ").join(`
14
+ `);const t=[`\u{1F50D} **brain_discover**${o?` \u2014 "${o}"`:""}${s?` \xB7 topic: ${s}`:""} (${e.length} result${e.length!==1?"s":""})`,""];for(const[a,r]of e.entries()){const l=new Date(r.created_at),c=isNaN(l.getTime())?"":` \xB7 ${l.toISOString().slice(0,10)}`,_=r.imports!=null?` \xB7 ${r.imports} imports`:"",i=r.topics?.length?` \xB7 topics: ${r.topics.slice(0,4).join(", ")}`:"",n=r.author?` by **${r.author}**`:"";t.push(`**${a+1}. ${r.title}**${n}`,` \u{1F4DA} ${r.lesson_count} lessons${i}${_}${c}`,r.description?` _${r.description.slice(0,120)}_`:"",` \`brain_import(instance_id="...", share_id="${r.share_id}")\``,"")}return t.push(`_Browse more at ${T("/brains","brain-discover")}_`),t.filter(a=>a!==" ").join(`
15
15
  `)}case"brain_seed_starter":{const{instance_id:o,topic_filter:s,dry_run:h=!1,force:e=!1}=w;if(!o)return"\u26A0\uFE0F `brain_seed_starter` requires `instance_id`.";const t=await y(o),a=await t.get(`cachly:brain:starter_seeded:${o}`);if(a&&!e&&!h)return["\u{1F331} **brain_seed_starter** \u2014 already seeded","",`This Brain was seeded with the starter corpus on ${a}.`,"","Pass `force=true` to re-seed (existing starter lessons will be refreshed)."].join(`
16
16
  `);const r=Array.isArray(s)&&s.length>0?s:void 0,l=r?k.filter(n=>r.some(d=>n.topic.includes(d)||n.tags.some(b=>b.includes(d)))):k;if(l.length===0)return["\u{1F331} **brain_seed_starter** \u2014 no matching starter lessons","",`No starter lessons match filter: ${r?.join(", ")}.`,`Available topics: ${k.map(n=>`\`${n.topic}\``).join(", ")}`].join(`
17
17
  `);if(h){const n=l.slice(0,8).map(d=>` \u2705 \`${d.topic}\` \u2014 ${d.what_worked.slice(0,70)}\u2026`);return[`\u{1F331} **brain_seed_starter (DRY RUN)** \u2014 would seed ${l.length} lesson${l.length!==1?"s":""}`,"",...n,l.length>8?` _...and ${l.length-8} more_`:"","","_Remove `dry_run=true` to seed these into the Brain._"].filter(d=>d!=="").join(`
18
- `)}const c=new Date().toISOString();let _=0,i=0;for(const n of l){const d=`cachly:lesson:best:${n.topic}`;if(!e){const p=await t.get(d);if(p){const f=T(p,null);if(f&&f.source!=="starter"){i++;continue}}}const b=JSON.stringify({topic:n.topic,outcome:n.outcome,what_worked:n.what_worked,what_failed:n.what_failed,ctx:n.ctx,tags:n.tags,confidence:n.confidence,recall_count:0,source:"starter",ts:c,verified_at:c,version:3});await t.set(d,b),await t.sadd("cachly:vek:nachtrag",n.topic).catch(()=>{});const u=`cachly:lessons:${n.topic}`;await t.rpush(u,b),await t.ltrim(u,-100,-1),await t.expire(u,90*86400),_++}return await t.set(`cachly:stats:born_at:${o}`,c,"EX",365*86400,"NX").catch(()=>{}),await t.set(`cachly:brain:starter_seeded:${o}`,c,"EX",365*86400),["\u{1F331} **brain_seed_starter** \u2014 Brain seeded","",`**${_}** universal engineering lesson${_!==1?"s":""} added${i>0?` (${i} skipped \u2014 your own lessons take priority)`:""}.`,"","Your Brain now answers common questions out of the box:",' \u2022 `smart_recall(query="docker build slow")`',' \u2022 `smart_recall(query="pod OOMKilled")`',' \u2022 `smart_recall(query="jwt token rejected")`',"",'_Starter lessons are tagged `source: "starter"` and never override your own._',"_They're replaced as you learn project-specific lessons on the same topics._"].join(`
19
- `)}default:return null}}export{E as SHARE_TOOL_NAMES,x as STARTER_CORPUS_SIZE,A as handleShareTool};
18
+ `)}const c=new Date().toISOString();let _=0,i=0;for(const n of l){const d=`cachly:lesson:best:${n.topic}`;if(!e){const p=await t.get(d);if(p){const m=j(p,null);if(m&&m.source!=="starter"){i++;continue}}}const b=JSON.stringify({topic:n.topic,outcome:n.outcome,what_worked:n.what_worked,what_failed:n.what_failed,ctx:n.ctx,tags:n.tags,confidence:n.confidence,recall_count:0,source:"starter",ts:c,verified_at:c,version:3});await t.set(d,b),await t.sadd(R,n.topic).catch(()=>{});const u=`cachly:lessons:${n.topic}`;await t.rpush(u,b),await t.ltrim(u,-100,-1),await t.expire(u,90*86400),_++}return await t.set(`cachly:stats:born_at:${o}`,c,"EX",365*86400,"NX").catch(()=>{}),await t.set(`cachly:brain:starter_seeded:${o}`,c,"EX",365*86400),["\u{1F331} **brain_seed_starter** \u2014 Brain seeded","",`**${_}** universal engineering lesson${_!==1?"s":""} added${i>0?` (${i} skipped \u2014 your own lessons take priority)`:""}.`,"","Your Brain now answers common questions out of the box:",' \u2022 `smart_recall(query="docker build slow")`',' \u2022 `smart_recall(query="pod OOMKilled")`',' \u2022 `smart_recall(query="jwt token rejected")`',"",'_Starter lessons are tagged `source: "starter"` and never override your own._',"_They're replaced as you learn project-specific lessons on the same topics._"].join(`
19
+ `)}default:return null}}export{q as SHARE_TOOL_NAMES,x as STARTER_CORPUS_SIZE,J as handleShareTool};