@cachly-dev/mcp-server 0.10.185 → 0.10.187
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 +6 -6
- package/dist/src/einblendung.js +4 -4
- package/dist/src/embeddings.js +2 -2
- package/dist/src/gueltigkeit-version.js +4 -0
- package/dist/src/handlers/brain.js +63 -63
- package/dist/src/handlers/cache.js +28 -32
- package/dist/src/index.js +104 -104
- package/dist/src/tools.js +1 -1
- package/glama.json +1 -1
- package/hooks/cachly-ambient-einblendung.mjs +20 -17
- package/package.json +4 -3
- package/server.json +3 -3
package/README.md
CHANGED
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
> the right moment. You build faster, and your team builds on what you figured out.
|
|
7
7
|
|
|
8
8
|
[](https://www.npmjs.com/package/@cachly-dev/mcp-server)
|
|
9
|
-

|
|
10
9
|

|
|
11
10
|
|
|
12
11
|
`@cachly-dev/mcp-server` connects [cachly](https://cachly.dev) to Claude Code, Cursor,
|
|
13
12
|
GitHub Copilot, Windsurf, Cline, Continue.dev, Zed, Codex CLI and Gemini CLI over
|
|
14
|
-
[MCP](https://modelcontextprotocol.io). It offers 124 MCP tools. Your
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
[MCP](https://modelcontextprotocol.io). It offers 124 MCP tools. Your editor lists 27 entries
|
|
14
|
+
by default and reaches the rest through one of them, `cachly_tool` (details under MCP
|
|
15
|
+
Tools below). Your AI stores a lesson after a fix, and finds it again when the same
|
|
16
|
+
problem returns. Your Brain (the store of your lessons) lives on EU servers.
|
|
17
17
|
|
|
18
18
|
## Start without an account
|
|
19
19
|
|
|
@@ -151,7 +151,7 @@ cachly_tool(tool: "team_roster", describe: true) get its schema first
|
|
|
151
151
|
|
|
152
152
|
Nothing is unreachable. The server dispatches by name, so `team_roster` called directly
|
|
153
153
|
still works. Set `CACHLY_ALLE_WERKZEUGE=1` to list all 124. Set `CACHLY_PROFILE=lean` to
|
|
154
|
-
list 8
|
|
154
|
+
list 8 plus `cachly_tool`, or `CACHLY_PROFILE=recall` to list the 3 read-only tools.
|
|
155
155
|
|
|
156
156
|
### Session and lessons (most used)
|
|
157
157
|
|
|
@@ -441,7 +441,7 @@ The free tier needs no credit card.
|
|
|
441
441
|
| `CACHLY_API_URL` | `https://api.cachly.dev` | Override for a self-hosted backend |
|
|
442
442
|
| `CACHLY_EMBED_PROVIDER` | automatic | Name an embedding provider yourself (see above) |
|
|
443
443
|
| `CACHLY_ALLE_WERKZEUGE` | unset | Set to `1` to list all 124 tools instead of 27 |
|
|
444
|
-
| `CACHLY_PROFILE` | unset | `lean` lists 8 tools
|
|
444
|
+
| `CACHLY_PROFILE` | unset | `lean` lists 8 tools plus `cachly_tool`, `recall` lists the 3 read-only tools |
|
|
445
445
|
| `CACHLY_UPDATE_CHECK` | on | Set to `false` to stop the version check. npm is asked at most once a day, with a 2-second limit |
|
|
446
446
|
| `CACHLY_NO_TELEMETRY` | unset | Set to `1` to disable usage pings. They include your API token and up to 80 characters of `smart_recall` queries |
|
|
447
447
|
|
package/dist/src/einblendung.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import{readFileSync as
|
|
1
|
+
import{readFileSync as I,existsSync as v,writeFileSync as b,mkdirSync as D,statSync as Y,appendFileSync as J}from"node:fs";import{dirname as k,join as h}from"node:path";import{tmpdir as m}from"node:os";import{createHash as q}from"node:crypto";import{spawn as Z}from"node:child_process";import{Einblendbestand as x,torWoerter as L}from"./einblendung-kern.js";import{rahmeEin as N}from"./einblendung-rahmen.js";import{leserText as z}from"./seltenheitsbestand.js";import{mischeMitLeser as C}from"./leser.js";import{LeserSicherung as F,dateiSpeicher as G,frageLeser as K}from"./leser-sicherung.js";import{LESER_TIEFE_EINBLENDUNG as W,LESER_ZEITLIMIT_MS as V}from"./rangfolge-stellschrauben.js";import{stufeEinblendungNachVersion as X}from"./gueltigkeit-version.js";export*from"./einblendung-kern.js";const Q=600*1e3,T=8e3,ee=60*1e3,j=120,$=W,te=1500,R=V,ne=h(m(),"cachly-ambient-netlog.jsonl");function be(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 o=0;o<8;o++){const r=h(n,".mcp.json");if(v(r))try{const i=JSON.parse(I(r,"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 s=k(n);if(s===n)break;n=s}return t}function S(e){return q("sha1").update(e).digest("hex").slice(0,12)}function re(e){return h(m(),`cachly-ambient-bestand-${S(e)}.json`)}function se(e){return h(m(),`cachly-leser-sicherung-${S(e)}.json`)}function oe(e){return h(m(),`cachly-ambient-auffrischen-${S(e)}.lock`)}async function M(e,{fetchFn:t=fetch,zeitlimitMs:n=T}={}){try{const o=await t(`${e.apiUrl}/api/v1/instances/${e.instanceId}/export`,{headers:{Authorization:`Bearer ${e.jwt}`},signal:AbortSignal.timeout(n)});if(!o.ok)return null;const r=await o.json();return Array.isArray(r?.lessons)?r.lessons.map(s=>typeof s=="string"?ie(s):s).filter(s=>!!s&&typeof s=="object"):null}catch{return null}}function ie(e){try{return JSON.parse(e)}catch{return null}}function H(e,t){try{D(k(e),{recursive:!0}),b(e,JSON.stringify({at:Date.now(),lessons:t}),{mode:384})}catch{}}function O(e){try{const t=JSON.parse(I(e,"utf8"));if(Array.isArray(t?.lessons))return{at:Number(t.at)||0,lessons:t.lessons}}catch{}return null}function ae(e,t){const n=oe(e.instanceId);try{if(v(n)&&Date.now()-Y(n).mtimeMs<ee)return;b(n,String(Date.now()),{mode:384})}catch{return}try{Z(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 ce(e,{force:t=!1,nebenlauf:n,abrufMs:o=T,fetchFn:r}={}){if(!e.jwt||!e.instanceId)return{lessons:[],quelle:"nicht-eingerichtet"};const s=re(e.instanceId);if(t){const c=await M(e,{fetchFn:r,zeitlimitMs:o});if(c)return H(s,c),{lessons:c,quelle:"server"};const l=O(s);return l?{lessons:l.lessons,quelle:"platte-alt"}:{lessons:[],quelle:"server-nicht-erreichbar"}}const i=O(s);if(i){const c=Date.now()-i.at<Q;return!c&&n&&ae(e,n),{lessons:i.lessons,quelle:c?"platte":"platte-alt"}}const u=await M(e,{fetchFn:r,zeitlimitMs:o});return u?(H(s,u),{lessons:u,quelle:"server"}):{lessons:[],quelle:"server-nicht-erreichbar"}}function g(e){return Math.ceil(String(e).length/4)}function E(e){const t=e.severity?`[${e.severity}] `:"",n=String(e.what_worked??"").replace(/\s+/g," ").trim(),o=n.length>j?`${n.slice(0,j)}\u2026`:n,r=typeof e.versionshinweis=="string"?` [${e.versionshinweis}]`:"";return`- ${t}${e.topic}${r}: ${o}`}const d={lessons:[],tokens:0,topScore:0,belege:0};function U(e,t,n){const o=[];let r=0;e=X(e);for(const{lektion:s}of e.slice(0,t)){const i=g(E(s));if(r+i>n)break;o.push(s),r+=i}return{lessons:o,tokens:r,topScore:Math.round(e[0].punkte*100)/100,belege:e[0].belege}}function ke(e,t,{minBelege:n=2,topK:o=3,tokenBudget:r=600}={}){if(!Array.isArray(t)||t.length===0)return{...d};if(L(e).length===0)return{...d};const s=new x(t).sortiere(e).filter(i=>i.belege>=n);return s.length===0?{...d}:U(s,o,r)}function le(e){return z(e,te)}async function B(e,t,n,{zeitlimitMs:o=R,fetchFn:r}={}){if(!e?.jwt||!e?.instanceId||n.length===0)return{art:"ohne"};if(["0","off","aus","false"].includes(String(process.env.CACHLY_LESER||"").toLowerCase()))return{art:"ohne"};const s=new F(G(se(e.instanceId)));return K({url:`${e.apiUrl}/api/v1/rerank`,jwt:e.jwt,frage:t,texte:n,instanceId:e.instanceId,zeitlimitMs:o,fetchFn:r},s)}async function xe(e,t,n,o={}){const r=await B(e,t,n,o);return r.art==="punkte"?{scores:r.scores,provider:r.provider,ms:r.ms}:null}async function ue(e,t,n,{minBelege:o=2,topK:r=3,tokenBudget:s=600,tiefe:i=$,zeitlimitMs:u=R,fetchFn:c}={}){const l={...d,leser:"aus",leserMs:0};if(!Array.isArray(t)||t.length===0||L(e).length===0)return l;let a=new x(t).sortiere(e).filter(p=>p.belege>=o);if(a.length===0)return l;let y="aus",w=0;if(a.length>1&&i>0){const p=a.slice(0,i),P=a.slice(i),f=await B(n,e,p.map(A=>le(A.lektion)),{zeitlimitMs:u,fetchFn:c});f.art==="punkte"?(a=[...C(p.map(_=>_.punkte),f.scores,1).map(_=>p[_]),...P],y=f.provider,w=f.ms):f.art==="uebersprungen"&&(y="uebersprungen")}return{...U(a,r,s),leser:y,leserMs:w}}function pe(e){if(!e.lessons.length)return"";const t=e.lessons.map(E).join(`
|
|
2
2
|
`);return`\u{1F9E0} Cachly Brain \u2014 relevant lessons for this task (auto-recall, ${e.lessons.length}):
|
|
3
3
|
${N(t)}
|
|
4
|
-
(ambient-recall \xB7 ~${e.tokens} tokens \xB7 match score ${e.topScore})`}const
|
|
4
|
+
(ambient-recall \xB7 ~${e.tokens} tokens \xB7 match score ${e.topScore})`}const fe=5;function Le(e){if(!e.length)return"";const t=e.filter(r=>{const s=String(r.topic??"");return!(/^auto:/.test(s)||/^[a-z]+:?$/.test(s))}),o=[...t.length?t:e].sort((r,s)=>(Number(s.recall_count)||0)-(Number(r.recall_count)||0)).slice(0,fe).map(E).join(`
|
|
5
5
|
`);return`\u{1F9E0} Cachly Brain \u2014 ambient recall active (${e.length} lessons). Top by proven reuse:
|
|
6
6
|
${N(o)}
|
|
7
|
-
(Relevant lessons for each task are auto-injected per prompt. ~${
|
|
8
|
-
`)}catch{}return{kontext:
|
|
7
|
+
(Relevant lessons for each task are auto-injected per prompt. ~${g(o)} tokens.)`}function Ne(e,t){return t?JSON.stringify({hookSpecificOutput:{hookEventName:e,additionalContext:t}}):""}async function Ce(e,t,{nebenlauf:n,abrufMs:o,leser:r=!0,session:s=null,protokoll:i=!0,fetchFn:u}={}){const{lessons:c,quelle:l}=await ce(t,{nebenlauf:n,abrufMs:o,fetchFn:u}),a=await ue(e,c,t,{tiefe:r?$:0,fetchFn:u});if(i)try{J(ne,JSON.stringify({at:Date.now(),session:s,prompt_tokens:g(e),injected_tokens:a.tokens,matches:a.lessons.length,top_score:a.topScore,belege:a.belege,leser:a.leser,leser_ms:a.leserMs,quelle:l,bestand:c.length})+`
|
|
8
|
+
`)}catch{}return{kontext:pe(a),auswahl:a,quelle:l,bestand:c.length}}export{T as ABRUF_TIMEOUT_MS,j as ANZEIGE_ZEICHEN,Q as BESTAND_TTL_MS,R as LESER_HOOK_ZEITLIMIT_MS,te as LESER_MAX_ZEICHEN,$ as LESER_TIEFE,ne as NETZ_PROTOKOLL,fe as SITZUNG_TOP_N,re as bestandPfad,g as estimateTokens,ce as holeBestand,Ne as hookAusgabe,B as leserAnfrageApi,xe as leserPunkteApi,le as leserText,C as mischeMitLeser,Ce as promptEinblendung,pe as promptKontext,E as renderLesson,be as resolveConfig,ke as selectRelevant,ue as selectRelevantMitLeser,se as sicherungsPfad,Le as sitzungsKontext,ae as starteNebenlauf};
|
package/dist/src/embeddings.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{zeitpunkt as u}from"./zeitmessung.js";const s={apiUrl:process.env.CACHLY_API_URL??"https://api.cachly.dev",jwt:process.env.CACHLY_JWT??"",model:process.env.CACHLY_EMBED_MODEL??""};function
|
|
1
|
+
import{zeitpunkt as u}from"./zeitmessung.js";const s={apiUrl:process.env.CACHLY_API_URL??"https://api.cachly.dev",jwt:process.env.CACHLY_JWT??"",model:process.env.CACHLY_EMBED_MODEL??""};function S(n){s.jwt=n,n&&!b&&c==="none"&&(c="cachly")}const A=Number(process.env.CACHLY_EMBED_TIMEOUT_MS??8e3),p=Number(process.env.CACHLY_EMBED_TIMEOUT_MAX_MS??45e3),h=12;function f(n,r){return r==="kurz"?A:Math.min(p,A+n.length*h)}function g(){return process.env.CACHLY_JWT?"cachly":process.env.OLLAMA_BASE_URL?"ollama":"none"}const b=!!process.env.CACHLY_EMBED_PROVIDER;let c=(process.env.CACHLY_EMBED_PROVIDER??g()).toLowerCase();async function I(n,r,a){const d=f(n,r);switch(c){case"cachly":{if(!s.jwt)throw new Error(`CACHLY_JWT not set.
|
|
2
2
|
|
|
3
3
|
The "cachly" provider uses server-side embeddings via the Cachly API.
|
|
4
4
|
Set CACHLY_JWT, or use another provider via CACHLY_EMBED_PROVIDER:
|
|
@@ -10,4 +10,4 @@ Set OPENAI_API_KEY in your .env, or switch provider:
|
|
|
10
10
|
CACHLY_EMBED_PROVIDER=gemini (+ GEMINI_API_KEY)
|
|
11
11
|
CACHLY_EMBED_PROVIDER=ollama (local, free)
|
|
12
12
|
CACHLY_EMBED_PROVIDER=cachly (server-side, no key needed)`);const o=s.model||"text-embedding-3-small",t=await fetch("https://api.openai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:o,input:n}),signal:AbortSignal.timeout(d)});if(!t.ok)throw new Error(`OpenAI embedding error: ${t.statusText}`);const i=await t.json();if(!i.data?.[0]?.embedding)throw new Error("OpenAI returned empty embedding response");return i.data[0].embedding}default:throw new Error(`Unknown CACHLY_EMBED_PROVIDER="${c}".
|
|
13
|
-
Supported: cachly (default), openai, mistral, cohere, ollama, gemini`)}}const y=3,
|
|
13
|
+
Supported: cachly (default), openai, mistral, cohere, ollama, gemini`)}}const y=3,C=4;function w(n){const r=n;if(typeof r?.status=="number")return r.status===429||r.status>=500;if(r?.name==="TimeoutError"||r?.name==="AbortError")return!1;if(/fetch failed/i.test(String(r?.message??"")))return!0;const a=r?.cause?.code??"";return["ECONNRESET","ECONNREFUSED","ETIMEDOUT","EAI_AGAIN","EPIPE","UND_ERR_SOCKET"].includes(a)}function M(n,r,a){if(r>=(a==="lang"?C:y)||!w(n))return null;const e=n?.retryAfterSek;if(typeof e=="number"&&Number.isFinite(e)&&e>=0){const o=e*1e3;return a==="kurz"?o<=2e3?o:null:Math.min(o,61e3)}return a==="lang"?Math.min(1e3*2**(r-1),8e3):250*2**(r-1)}async function L(n,r){const a=r?.geduld??"kurz";if(r?.modell&&c!=="cachly"&&c!=="ollama")throw new Error(`Anbieter "${c}" kann kein abweichendes Modell anfragen (verlangt: ${r.modell}).`);let d=0;for(;;){d++;try{u(`einbettung: Anfang (${n.length} Zeichen, Versuch ${d})`);const e=await I(n,a,r?.modell);return u("einbettung: fertig"),e}catch(e){const o=M(e,d,a);if(o===null)throw e;await new Promise(t=>setTimeout(t,o))}}}function T(){switch(c){case"cachly":return!!s.jwt;case"mistral":return!!process.env.MISTRAL_API_KEY;case"cohere":return!!process.env.COHERE_API_KEY;case"ollama":return!0;case"gemini":return!!process.env.GEMINI_API_KEY;case"openai":return!!process.env.OPENAI_API_KEY;case"none":return!1;default:return!1}}function v(){const n={cachly:"CACHLY_JWT (server-side, no extra key needed)",openai:"OPENAI_API_KEY",mistral:"MISTRAL_API_KEY",cohere:"COHERE_API_KEY",ollama:"OLLAMA_BASE_URL (optional, default: http://localhost:11434)",gemini:"GEMINI_API_KEY"};if(c==="none")return"No embedding provider configured. Sign in (CACHLY_JWT) to use the EU-hosted cachly embeddings, or set OLLAMA_BASE_URL for a local model. Brain works without embedding.";const r=n[c]??"CACHLY_JWT";return`CACHLY_EMBED_PROVIDER=${c} \u2192 requires ${r}`}export{c as EMBED_PROVIDER,L as computeEmbedding,s as embedConfig,v as embedProviderHint,T as hasEmbedProvider,w as istVoruebergehend,S as setEmbedJwt,M as wiederholungMs,f as zeitlimitMs};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import{createHash as K}from"node:crypto";import{existsSync as Y,readFileSync as T,renameSync as Q,statSync as P,writeFileSync as ee}from"node:fs";import{tmpdir as L}from"node:os";import{dirname as $,join as m,resolve as d,sep as te}from"node:path";const M=120,R=8;function j(n){const t=/^[vV=\s]*(\d+)(?:\.(\d+))?(?:\.(\d+))?/.exec(String(n??""));return t?[Number(t[1]),Number(t[2]??0),Number(t[3]??0)]:null}function I(n,t){for(let e=0;e<3;e++)if(n[e]!==t[e])return n[e]<t[e]?-1:1;return 0}function x(n,t){return t<=1?[n[0]+1,0,0]:t===2?[n[0],n[1]+1,0]:[n[0],n[1],n[2]+1]}const A="(<=|>=|===|==|!=|~>|~=|<|>|=|~|\\^)",S=new RegExp(`^${A}?[vV]?(\\d+)(?:\\.(\\d+|[xX*]))?(?:\\.(\\d+|[xX*]))?((?:\\.\\d+)*)((?:[-+_.]?[A-Za-z]|[-+])[0-9A-Za-z.+_-]*)?$`),ne=new RegExp(`^${A}?(\\*|[xX])$`);function w(n,t,e){const s=u=>u!==void 0&&/^\d+$/.test(u)?Number(u):null,r=Number(n),o=s(t),i=o===null?null:s(e);return{t:[r,o??0,i??0],n:o===null?1:i===null?2:3}}function re(n){const t=ne.exec(n);if(t)return t[1]&&t[1]!=="="&&t[1]!=="=="?null:{};const e=S.exec(n);if(!e||/[xX*]/.test(`${e[3]??""}${e[4]??""}`)&&(e[5]||e[6]))return null;const s=e[1]??"",{t:r,n:o}=w(e[2],e[3],e[4]);switch(s){case"":case"=":case"==":case"===":return{von:r,bis:x(r,o)};case"!=":return{von:r,bis:x(r,o),nicht:!0};case"<":return{bis:r};case"<=":return{bis:x(r,o)};case">":return{von:x(r,o)};case">=":return{von:r};case"^":return r[0]>0?{von:r,bis:[r[0]+1,0,0]}:o===1?{von:r,bis:[1,0,0]}:r[1]>0?{von:r,bis:[0,r[1]+1,0]}:o===2?{von:r,bis:[0,1,0]}:{von:r,bis:[0,0,r[2]+1]};case"~":return{von:r,bis:o===1?[r[0]+1,0,0]:[r[0],r[1]+1,0]};case"~>":case"~=":return{von:r,bis:o===3?[r[0],r[1]+1,0]:[r[0]+1,0,0]};default:return null}}function se(n){if(!n)return null;const t=/^(\S+)\s+-\s+(\S+)$/.exec(n);if(t){const o=S.exec(t[1]),i=S.exec(t[2]);if(!o||!i||o[1]||i[1])return null;const c=w(o[2],o[3],o[4]),u=w(i[2],i[3],i[4]);return[{von:c.t,bis:x(u.t,u.n)}]}const s=n.replace(/,/g," ").replace(new RegExp(`${A}\\s+`,"g"),"$1").trim().split(/\s+/);if(s.length>8)return null;const r=[];for(const o of s){const i=re(o);if(!i)return null;r.push(i)}return r}function D(n){if(typeof n!="string")return null;const t=n.trim();if(!t||t.length>M)return null;const e=[];for(const s of t.split("||")){const r=se(s.trim());if(!r)return null;e.push(r)}return e}function oe(n,t){let e=!0;return t.von&&I(n,t.von)<0&&(e=!1),t.bis&&I(n,t.bis)>=0&&(e=!1),t.nicht?!e:e}function ie(n,t){const e=j(n),s=D(t);return!e||!s?null:s.some(r=>r.every(o=>oe(e,o)))}const ce={npm:"npm",go:"go",python:"python",pypi:"python",pip:"python"};function F(n){if(typeof n!="string")return{fehler:"keine Zeichenkette"};const t=n.replace(/\s+/g," ").trim();if(!t)return{fehler:"leer"};if(t.length>M+80)return{fehler:"zu lang"};let e=t,s=null;const r=/^(npm|go|python|pypi|pip):/i.exec(e);r&&(s=ce[r[1].toLowerCase()],e=e.slice(r[0].length));const o=e.indexOf("@",1);if(o<0)return{fehler:'es fehlt "@bereich" (Form: paket@bereich)'};const i=e.slice(0,o).trim(),c=e.slice(o+1).trim();return!i||!/^[@A-Za-z0-9._~/+-]+$/.test(i)?{fehler:"Paketname unlesbar"}:D(c)?{angabe:{text:t,oekosystem:s,paket:i,bereichText:c}}:{fehler:`Bereich "${c.slice(0,40)}" unlesbar`}}function q(n){const t=Array.isArray(n)?n:n==null?[]:[n],e=[],s=[];for(const r of t){const o=F(r);"fehler"in o?s.push(`"${String(r).slice(0,60)}": ${o.fehler}`):e.includes(o.angabe.text)||(e.length>=R?s.push(`"${o.angabe.text.slice(0,60)}": mehr als ${R} Angaben`):e.push(o.angabe.text))}return{angaben:e,fehler:s}}function Oe(n,t){if(n==null){const e=Array.isArray(t)?q(t).angaben:[];return{angaben:e,fehler:[],uebernommen:e.length>0}}return{...q(n),uebernommen:!1}}const y=["package.json","go.mod","pyproject.toml","requirements.txt","package-lock.json"],ue={"package.json":1<<20,"go.mod":1<<19,"pyproject.toml":1<<19,"requirements.txt":1<<19,"package-lock.json":3<<20},le=25,ae=600*1e3,fe=4e3,C=new WeakMap;function g(n,t,e,s=!1){if(t==="__proto__")return;const r=Object.hasOwn(n,t);if(!(r&&!s)){if(!r){const o=C.get(n)??0;if(o>=fe)return;C.set(n,o+1)}n[t]=e}}function E(n,t){return Object.hasOwn(n,t)?n[t]:null}function G(n,t){try{const e=P(n,{throwIfNoEntry:!1});return!e||!e.isFile()||e.size>t?null:T(n,"utf8").replace(/^\uFEFF/,"")}catch{return null}}function N(n){return n.toLowerCase().replace(/[-_.]+/g,"-")}function pe(n){if(typeof n!="string")return null;const t=n.trim();if(!t||t.includes("||")||/[xX*]$/.test(t))return null;const e=/^(?:===?|=)?\s*v?(\d+(?:\.\d+){0,2})(?:[-+.]?[0-9A-Za-z.+_-]*)?$/.exec(t);if(e)return{version:e[1],ab:!1};const s=/(?:\^|~>|~=|~|>=|>)\s*v?(\d+(?:\.\d+){0,2})/.exec(t);return s?{version:s[1],ab:!0}:null}function _(n,t,e,s){const r=pe(e);r&&g(n,t,{version:r.version,quelle:s,...r.ab?{ab:!0}:{}})}function he(n,t){let e;try{e=JSON.parse(n)}catch{return}if(!(!e||typeof e!="object"))for(const s of["dependencies","devDependencies","optionalDependencies"]){const r=e[s];if(!(!r||typeof r!="object"))for(const[o,i]of Object.entries(r))_(t,o.toLowerCase(),i,"package.json")}}function de(n,t){let e;try{e=JSON.parse(n)}catch{return}if(!e||typeof e!="object")return;const s=(r,o)=>{typeof o!="string"||!j(o)||g(t,r.toLowerCase(),{version:o,quelle:"package-lock.json"},!0)};if(e.packages&&typeof e.packages=="object")for(const[r,o]of Object.entries(e.packages))!r.startsWith("node_modules/")||r.indexOf("node_modules/",13)>=0||s(r.slice(13),o?.version);else if(e.dependencies&&typeof e.dependencies=="object")for(const[r,o]of Object.entries(e.dependencies))s(r,o?.version)}function ge(n,t){let e=!1;const s=r=>{const o=/^(\S+)\s+(v\d\S*)/.exec(r);o&&g(t,o[1],{version:o[2].replace(/^v/,""),quelle:"go.mod"})};for(const r of n.split(`
|
|
2
|
+
`)){const o=r.replace(/\/\/.*$/,"").trim();if(!o)continue;if(e){o===")"?e=!1:s(o);continue}const i=/^go\s+(\d+(?:\.\d+){0,2})\b/.exec(o);if(i){g(t,"go",{version:i[1],quelle:"go.mod",ab:!0});continue}if(/^require\s*\($/.test(o)){e=!0;continue}const c=/^require\s+(.+)$/.exec(o);c&&s(c[1])}}function Z(n,t,e){if(n.includes("://"))return;const s=n.split("#")[0].split(";")[0].trim(),r=/^([A-Za-z0-9][A-Za-z0-9._-]*)\s*(?:\[[^\]]*\])?\s*(.*)$/.exec(s);if(!r||!r[2])return;const o=r[2].replace(/^\(|\)$/g,"").split(",").map(l=>l.trim()),i=N(r[1]),c=o.map(l=>/^===?\s*(\d+(?:\.\d+){0,2})(?:\.\*)?$/.exec(l)).find(Boolean),u=o.map(l=>/^(?:>=|~=|>)\s*(\d+(?:\.\d+){0,2})/.exec(l)).find(Boolean);c?g(t,i,{version:c[1],quelle:e}):u&&g(t,i,{version:u[1],quelle:e,ab:!0})}function be(n,t){for(const e of n.split(`
|
|
3
|
+
`)){const s=e.trim();!s||s.startsWith("#")||s.startsWith("-")||Z(s,t,"requirements.txt")}}function me(n,t){let e="",s=!1;const r=o=>[...o.matchAll(/"([^"]+)"|'([^']+)'/g)].map(i=>i[1]??i[2]);for(const o of n.split(`
|
|
4
|
+
`)){const i=o.trim();if(!i||i.startsWith("#"))continue;const c=/^\[\[?([^\]]+)\]\]?$/.exec(i);if(c){e=c[1].trim(),s=!1;continue}if((e==="project"?/^dependencies\s*=\s*\[/.test(i):e==="project.optional-dependencies"||e==="dependency-groups"?/^[\w.-]+\s*=\s*\[/.test(i):!1)||s){for(const l of r(i.replace(/^[\w.-]+\s*=\s*\[/,"")))Z(l,t,"pyproject.toml");s=!i.includes("]");continue}if(e==="project"){const l=/^requires-python\s*=\s*["']([^"']+)["']/.exec(i);l&&_(t,"python",l[1],"pyproject.toml");continue}if(/^tool\.poetry(?:\.group\.[^.]+)?\.(?:dev-)?dependencies$/.test(e)){const l=/^([A-Za-z0-9._-]+)\s*=\s*(.+)$/.exec(i);if(!l)continue;const f=l[2].trim(),p=/^["']/.test(f)?r(f)[0]:/version\s*=\s*["']([^"']+)["']/.exec(f)?.[1];_(t,N(l[1]),p,"pyproject.toml")}}}function X(){return{npm:{},go:{},python:{}}}const b=new Map;function xe(n){const t={};for(const e of y)try{const s=P(m(n,e),{throwIfNoEntry:!1});t[e]=s?`${Math.round(s.mtimeMs)}:${s.size}`:"-"}catch{t[e]="-"}return t}function ye(n,t){return y.every(e=>n[e]===t[e])}function O(n,t){return m(n,`cachly-projektversionen-${K("sha1").update(t).digest("hex").slice(0,12)}.json`)}function ve(n,t){try{const e=JSON.parse(T(n,"utf8"));return e&&e.v===1&&e.ordner===t&&e.stand&&e.stempel?e:null}catch{return null}}function ke(n,t){try{const e=`${n}.${process.pid}.tmp`;ee(e,JSON.stringify(t),{mode:384}),Q(e,n)}catch{}}function $e(n,t,e){const s=X(),r=e();let o=!1,i=!0;for(const c of y){if(!i&&e()-r>t){o=!0;break}const u=G(m(n,c),ue[c]);if(u!==null)switch(i=!1,c){case"package.json":he(u,s.npm);break;case"package-lock.json":de(u,s.npm);break;case"go.mod":ge(u,s.go);break;case"pyproject.toml":me(u,s.python);break;case"requirements.txt":be(u,s.python);break}}return{stand:s,unvollstaendig:o}}function je(n,t){if(!/^[@a-z0-9._~/-]+$/.test(t)||t.includes(".."))return null;let e=n;for(let s=0;s<4;s++){const r=G(m(e,"node_modules",t,"package.json"),262144);if(r!==null){try{const i=JSON.parse(r).version;if(typeof i=="string"&&j(i))return{version:i,quelle:"node_modules"}}catch{}return null}const o=$(e);if(o===e)break;e=o}return null}function Ae(n,t){let e=d(n);const s=t?d(t):null;for(let r=0;s&&r<6;r++){if(y.some(i=>Y(m(e,i))))return e;if(e===s)break;const o=$(e);if(o===e)break;e=o}return d(n)}function B(){return process.env.CACHLY_WORKSPACE||process.env.CLAUDE_PROJECT_DIR||process.cwd()}function v(n=B(),t={}){const e=Ae(n,t.obergrenze),s=t.jetzt??(()=>performance.now()),r=t.ablageOrdner===void 0?L():t.ablageOrdner;let o="gebaut",i=X(),c=!1;try{const f=xe(e),p=a=>!!a&&ye(a.stempel,f)&&(!a.unvollstaendig||Date.now()-a.at<ae),h=b.get(e);if(p(h))({stand:i,unvollstaendig:c}=h),o="speicher";else{const a=r===null?null:ve(O(r,e),e);if(p(a))b.set(e,a),{stand:i,unvollstaendig:c}=a,o="platte";else{({stand:i,unvollstaendig:c}=$e(e,t.budgetMs??le,s));const V={v:1,ordner:e,stempel:f,stand:i,unvollstaendig:c,at:Date.now()};b.size>20&&b.clear(),b.set(e,V),r!==null&&ke(O(r,e),V)}}}catch{}const u=new Map;return{ordner:e,herkunft:o,unvollstaendig:c,suche:(f,p)=>{const h=`${f??"*"}:${p}`;if(u.has(h))return u.get(h)??null;let a=null;if(f===null||f==="npm"){const k=p.toLowerCase();a=je(e,k)??E(i.npm,k)}return!a&&(f===null||f==="python")&&(a=E(i.python,N(p))),!a&&(f===null||f==="go")&&(a=E(i.go,p)),u.set(h,a),a}}}function ze(n,t=L()){return O(t,d(n))}function Ve(){b.clear()}function J(n){return n.ab?`ab ${n.version} laut ${n.quelle}`:n.version}function z(n){return Array.isArray(n)?n:typeof n=="string"&&n.trim()?[n]:[]}function W(n){return z(n).length>0}function H(n,t){const e=[],s=[];for(const r of z(n)){const o=F(r);if("fehler"in o)continue;const i=o.angabe,c=t.suche(i.oekosystem,i.paket);if(!c)continue;const u=ie(c.version,i.bereichText);u!==null&&(u?s.push({angabe:i.text,paket:i.paket,hier:J(c)}):e.push({angabe:i.text,hier:J(c)}))}return e.length>0?{art:"passtNicht",abweichungen:e,text:e.map(r=>`gilt fuer ${r.angabe}, hier ${r.hier}`).join("; ")}:s.length>0?{art:"passt",geprueft:s}:{art:"unbekannt"}}function U(n,t){const e=new Map,s=[],r=[];let o=null,i=!1;for(const c of n){const u=t.giltFuerVon(c);if(!W(u)){s.push(c);continue}if(!o&&!i)try{o=(t.leser??(()=>v()))()}catch{i=!0}const l=o?H(u,o):{art:"unbekannt"};l.art==="passtNicht"?(e.set(t.schluesselVon(c),l.text),r.push(c)):s.push(c)}return{treffer:r.length>0?[...s,...r]:[...s],hinweise:e}}function Se(n){const t=d(B()),e=n.find(s=>typeof s=="string"&&s.length>0);if(e){const s=$(d(t,e));if(s===t||s.startsWith(t+te))return{start:s,obergrenze:t}}return{start:t}}function Te(n,t=[],e={}){const s="cachly:lesson:best:",r=U(n,{giltFuerVon:o=>{if(!(!o.key.startsWith(s)||typeof o.content!="string"||!o.content.includes('"gilt_fuer"')))try{return JSON.parse(o.content).gilt_fuer}catch{return}},schluesselVon:o=>o.key,leser:()=>{const o=Se(t);return v(o.start,{obergrenze:o.obergrenze,...e})}});return r.hinweise.size>0&&n.splice(0,n.length,...r.treffer),r.hinweise}function Pe(n,t){const e=[];for(const s of n){const r=t.get(s.key);r&&e.push(`\u26A0\uFE0F \`${s.key.replace("cachly:lesson:best:","")}\` ${r} \u2014 passt nicht zu den Versionen dieses Projekts, steht deshalb hinter den passenden Treffern.`)}return e}function Le(n,t={}){if(!W(n))return"";let e;try{e=H(n,t.leser??v(void 0,t))}catch{e={art:"unbekannt"}}const s=z(n).filter(r=>typeof r=="string").join(", ");return e.art==="passtNicht"?`\u26A0\uFE0F **GILT NICHT FUER DIESEN STAND** \u2014 ${e.text}. Der Text unten bleibt lesbar, ist fuer diese Version aber nicht gesichert.`:e.art==="passt"?`\u{1F4E6} Gilt fuer ${s} \u2014 passt zu diesem Projekt (${e.geprueft.map(r=>`${r.paket} ${r.hier}`).join(", ")}).`:`\u{1F4E6} Gilt fuer ${s} \u2014 die Version in diesem Projekt ist nicht bekannt.`}function Me(n,t={}){const e=U(n,{giltFuerVon:s=>s.lektion.gilt_fuer,schluesselVon:s=>String(s.lektion.topic??""),leser:t.leser??(()=>v(void 0,t))});return e.hinweise.size===0?n:e.treffer.map(s=>{const r=e.hinweise.get(String(s.lektion.topic??""));return r?{...s,lektion:{...s.lektion,versionshinweis:r}}:s})}export{M as BEREICH_MAX_ZEICHEN,R as GILT_FUER_MAX,le as LESE_BUDGET_MS,ae as UNVOLLSTAENDIG_MS,ze as ablageDatei,B as arbeitsordner,H as beurteileGiltFuer,Ae as findeProjektOrdner,Ve as leereVersionsSpeicher,v as leseProjektVersionen,F as liesAngabe,D as liesBereich,j as liesVersion,Oe as loeseGiltFuerAuf,ie as passtVersion,q as pruefeGiltFuer,Me as stufeEinblendungNachVersion,U as stufeNachVersion,Te as stufeSucheNachProjektversion,W as traegtGiltFuer,Le as versionsBanner,Pe as versionsNotizen};
|