@cachly-dev/mcp-server 0.10.229 → 0.10.231

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,10 @@
1
- import{existsSync as H,readFileSync as R}from"node:fs";import{readFile as j,writeFile as T,chmod as L,mkdir as x}from"node:fs/promises";import{dirname as G,resolve as l}from"node:path";import{fileURLToPath as rt}from"node:url";import{CURSOR_FLAG as nt}from"./cursor-hook.js";import{COPILOT_FLAG as st,COPILOT_HOOK_EVENTS as it}from"./copilot-hook.js";import{CODEX_FLAG as ct,CODEX_HOOK_EVENTS as at}from"./codex-hook.js";import{GEMINI_FLAG as ut,GEMINI_HOOK_EVENTS as mt}from"./gemini-hook.js";import{istCachlyEintrag as M}from"./hook-zugang.js";const v="v5",qt="ambient-recall",S="cachly-ambient-einblendung.mjs";function U(t){return t.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}function C(t,o){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${v}`,"// Pushes relevant memory into context automatically. Cross-platform Node hook","// (no shell script \u2014 runs identically on Windows/macOS/Linux). Never blocks","// the agent: every failure path exits 0 with no output (graceful degrade).",`// Runs the hook bundle next to this file (${S}) in this process.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${U(o.instanceId)}';`,`process.env.CACHLY_HOOK_EVENT = '${U(t)}';`,`process.argv.splice(2, process.argv.length, '${U(t)}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
2
- `)}function K(){const t=G(rt(import.meta.url));for(const o of[l(t,"..",$,S),l(t,"..","..",$,S)])if(H(o))return o;return null}function pt(t){return C("SessionStart",t)}function lt(t){return C("UserPromptSubmit",t)}function St(t){return C("PreToolUse",t)}function ft(t){return C("Stop",t)}const ht={SessionStart:30,UserPromptSubmit:10,PreToolUse:10,Stop:60},dt="Edit|Write|MultiEdit|NotebookEdit";function J(t,o){const e=(r,i,m)=>({...m?{matcher:m}:{},hooks:[{type:"command",command:`node "${i}"${o?` ${o(r)}`:""}`,timeout:ht[r]}]}),s={SessionStart:[e("SessionStart",t.sessionStart)],UserPromptSubmit:[e("UserPromptSubmit",t.userPromptSubmit)]};return t.preToolUse&&(s.PreToolUse=[e("PreToolUse",t.preToolUse,dt)]),t.stop&&(s.Stop=[e("Stop",t.stop)]),s}const B=".claude/hooks",bt=".claude/settings.json",F={SessionStart:"cachly-ambient-session-start.mjs",UserPromptSubmit:"cachly-ambient-prompt-submit.mjs",PreToolUse:"cachly-ambient-pre-tool.mjs",Stop:"cachly-ambient-stop.mjs"},gt=".claude/hooks/cachly-ambient-";function kt(t,o){const e=t.hooks??[];return e.length>0&&e.every(s=>{const r=s.command??"";return r.replace(/\\/g,"/").includes(gt)||o.has(r)||[...o].some(i=>r.includes(`"${i}"`))})}function Ot(t,o){const e={...t,hooks:{...t.hooks??{}}},s=e.hooks,r=J(o),i=new Set([o.sessionStart,o.userPromptSubmit,o.preToolUse,o.stop].filter(c=>!!c));for(const[c,n]of Object.entries(r)){const u=(Array.isArray(s[c])?s[c]:[]).filter(f=>!kt(f,i));s[c]=[...u,...n]}const m=JSON.stringify(e)!==JSON.stringify(t);return{settings:e,changed:m}}async function to(t,o,e,s={}){const r=l(t,B),i={instanceId:o,apiKey:e},m=["SessionStart","UserPromptSubmit","PreToolUse","Stop"],c={SessionStart:pt(i),UserPromptSubmit:lt(i),PreToolUse:St(i),Stop:ft(i)},n=a=>l(r,F[a]),u=K();if(!u)throw new Error(`cachly hook bundle ${S} missing from the package`);const f=R(u,"utf-8"),d=l(r,S),O=async a=>{try{return await j(a,"utf-8")}catch{return""}},E=l(t,bt),_=H(E);let b={};if(_){const a=await O(E);try{const g=a.charCodeAt(0)===65279?a.slice(1):a,P=g.trim()?JSON.parse(g):{};if(!w(P))throw new k("is not a JSON object");if(P.hooks!==void 0&&!w(P.hooks))throw new k('has a "hooks" field that is not an object');b=P}catch(g){const P=g instanceof k?g.message:/^\s*\/\/|\/\*/m.test(a)?"has comments, and cachly only rewrites plain JSON":"is not valid JSON";return{sessionStartPath:n("SessionStart"),promptSubmitPath:n("UserPromptSubmit"),preToolUsePath:n("PreToolUse"),stopPath:n("Stop"),bundlePath:d,scripts:"unchanged",settings:"skipped",grund:P}}}let p=!1,h=await O(d)===f;for(const a of m){const g=await O(n(a));g&&(p=!0),g!==c[a]+`
3
- `&&(h=!1)}const D=h?"unchanged":p?"upgraded":"written";if(D!=="unchanged"){await x(r,{recursive:!0}),await T(d,f,"utf-8");for(const a of m)await T(n(a),c[a]+`
4
- `,"utf-8"),await L(n(a),493).catch(()=>{})}const I=a=>s.portable!==!1?`\${CLAUDE_PROJECT_DIR}/${B}/${F[a]}`:n(a),{settings:ot,changed:et}=Ot(b,{sessionStart:I("SessionStart"),userPromptSubmit:I("UserPromptSubmit"),preToolUse:I("PreToolUse"),stop:I("Stop")});let y;return _?et?y="merged":y="unchanged":y="written",y!=="unchanged"&&(await x(l(t,".claude"),{recursive:!0}),await T(E,JSON.stringify(ot,null,2)+`
5
- `,"utf-8")),{sessionStartPath:n("SessionStart"),promptSubmitPath:n("UserPromptSubmit"),preToolUsePath:n("PreToolUse"),stopPath:n("Stop"),bundlePath:d,scripts:D,settings:y}}const V=".cursor/hooks",Pt=".cursor/hooks.json",X="cachly-ambient-cursor.mjs",Tt={sessionStart:30,beforeSubmitPrompt:10,postToolUse:5};function N(t,o,e,s){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${v}`,`// Einblendung fuer ${t}: ${e.join(", ")}.`,"// Blockiert nie: jeder Fehler endet mit Exit 0. Ruft das Buendel daneben",`// (${S}) in diesem Prozess.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${U(s.instanceId)}';`,`process.argv.push('${o}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
6
- `)}function _t(t){return N("Cursor",nt,["sessionStart","beforeSubmitPrompt","postToolUse"],t)}function yt(){const t=o=>[{command:`node ${V}/${X} ${o}`,timeout:Tt[o]}];return{sessionStart:t("sessionStart"),beforeSubmitPrompt:t("beforeSubmitPrompt"),postToolUse:t("postToolUse")}}function Et(t){return z(t,yt())}function z(t,o){const e={...t.hooks??{}};for(const[r,i]of Object.entries(o)){W(e[r],r);const m=(e[r]??[]).filter(c=>!M(c));e[r]=[...m,...i]}const s={...t,version:typeof t.version=="number"?t.version:1,hooks:e};return{datei:s,changed:JSON.stringify(s)!==JSON.stringify(t)}}function Y(t,o){const e={...t.hooks??{}};for(const[r,i]of Object.entries(o)){W(e[r],r);const m=(e[r]??[]).flatMap(c=>{const n=c?.hooks;if(!Array.isArray(n))return[c];const u=n.filter(f=>!M(f));return u.length===n.length?[c]:u.length?[{...c,hooks:u}]:[]});e[r]=[...m,...i]}const s={...t,hooks:e};return{datei:s,changed:JSON.stringify(s)!==JSON.stringify(t)}}async function A(t){const o=l(t.projectDir,t.hookDir),e=K();if(!e)throw new Error(`cachly hook bundle ${S} missing from the package`);const s=R(e,"utf-8"),r=l(o,S),i=l(o,t.skriptName),m=t.skript+`
7
- `,c=async p=>{try{return await j(p,"utf-8")}catch{return""}},n=l(t.projectDir,t.configDatei),u=H(n)?await c(n):"",f=!u.trim();let d;try{const p=u.charCodeAt(0)===65279?u.slice(1):u,h=f?{}:JSON.parse(p);if(!w(h))throw new k("is not a JSON object");if(h.hooks!==void 0&&!w(h.hooks))throw new k('has a "hooks" field that is not an object');d=t.merge(h,i)}catch(p){const h=p instanceof k?p.message:/^\s*\/\/|\/\*/m.test(u)?"has comments, and cachly only rewrites plain JSON":"is not valid JSON";return{scriptPath:i,bundlePath:r,hooksPath:n,scripts:"unchanged",hooks:"skipped",grund:h}}await x(o,{recursive:!0});const O=await c(i),_=O===m&&await c(r)===s?"unchanged":O?"upgraded":"written";_!=="unchanged"&&(await T(r,s,"utf-8"),await T(i,m,"utf-8"),await L(i,493).catch(()=>{}));let b;if(f?b="written":d.changed?b="merged":b="unchanged",b!=="unchanged"){const p=/^([ \t]+)"/m.exec(u)?.[1]??2;await x(G(n),{recursive:!0}),await T(n,JSON.stringify(d.datei,null,p)+`
8
- `,"utf-8")}return{scriptPath:i,bundlePath:r,hooksPath:n,scripts:_,hooks:b}}function w(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}class k extends Error{}function W(t,o){if(t!==void 0&&!Array.isArray(t))throw new k(`has a "hooks.${o}" entry that is not a list`)}async function oo(t,o){return A({projectDir:t,hookDir:V,skriptName:X,skript:_t({instanceId:o}),configDatei:Pt,merge:e=>Et(e)})}const Q=".github/hooks",It=".github/hooks/cachly-ambient.json",Z="cachly-ambient-copilot.mjs",xt={sessionStart:30,userPromptSubmitted:10,postToolUse:5};function Ut(t){return N("VS Code / Copilot",st,it,t)}function Ct(){const t=o=>[{type:"command",command:`node ${Q}/${Z} ${o}`,cwd:".",timeoutSec:xt[o]}];return{sessionStart:t("sessionStart"),userPromptSubmitted:t("userPromptSubmitted"),postToolUse:t("postToolUse")}}function Nt(t){return z(t,Ct())}async function eo(t,o){return A({projectDir:t,hookDir:Q,skriptName:Z,skript:Ut({instanceId:o}),configDatei:It,merge:e=>Nt(e)})}const At=".codex/hooks",wt=".codex/hooks.json",Ht="cachly-ambient-codex.mjs",$t={SessionStart:30,UserPromptSubmit:10};function Dt(t){return N("Codex",ct,at,t)}function Rt(t){const o=e=>[{hooks:[{type:"command",command:`node "${t}" ${e}`,timeout:$t[e]}]}];return{SessionStart:o("SessionStart"),UserPromptSubmit:o("UserPromptSubmit")}}function jt(t,o){return Y(t,Rt(o))}async function ro(t,o){return A({projectDir:t,hookDir:At,skriptName:Ht,skript:Dt({instanceId:o}),configDatei:wt,merge:(e,s)=>jt(e,s)})}const q=".gemini/hooks",Lt=".gemini/settings.json",tt="cachly-ambient-gemini.mjs",Gt={SessionStart:3e4,BeforeAgent:1e4},Mt={SessionStart:"cachly-briefing",BeforeAgent:"cachly-recall"};function vt(t){return N("Gemini CLI",ut,mt,t)}function Kt(){const t=o=>[{hooks:[{name:Mt[o],type:"command",command:`node ${q}/${tt} ${o}`,timeout:Gt[o]}]}];return{SessionStart:t("SessionStart"),BeforeAgent:t("BeforeAgent")}}function Jt(t){return Y(t,Kt())}async function no(t,o){return A({projectDir:t,hookDir:q,skriptName:tt,skript:vt({instanceId:o}),configDatei:Lt,merge:e=>Jt(e)})}const so=["SessionStart","UserPromptSubmit","Stop"],$="hooks";function io(){const t=`\${CLAUDE_PLUGIN_ROOT}/${$}/${S}`,o=J({sessionStart:t,userPromptSubmit:t,stop:t},e=>`${e} --plugin`);return JSON.stringify({hooks:o},null,2)+`
9
- `}export{qt as AMBIENT_CLI_SUBCOMMAND,v as AMBIENT_HOOK_VERSION,B as CLAUDE_HOOK_DIR,bt as CLAUDE_SETTINGS_DATEI,wt as CODEX_HOOKS_DATEI,At as CODEX_HOOK_DIR,Ht as CODEX_SKRIPT,$t as CODEX_TIMEOUTS,It as COPILOT_HOOKS_DATEI,Q as COPILOT_HOOK_DIR,Z as COPILOT_SKRIPT,xt as COPILOT_TIMEOUTS,Pt as CURSOR_HOOKS_DATEI,V as CURSOR_HOOK_DIR,X as CURSOR_SKRIPT,Tt as CURSOR_TIMEOUTS,q as GEMINI_HOOK_DIR,Lt as GEMINI_SETTINGS_DATEI,tt as GEMINI_SKRIPT,Gt as GEMINI_TIMEOUTS_MS,S as HOOK_BUENDEL,$ as PLUGIN_HOOK_DIR,so as PLUGIN_HOOK_EVENTS,dt as PRE_TOOL_USE_MATCHER,J as buildAmbientSettingsHooks,Dt as buildCodexHook,Rt as buildCodexHooks,Ut as buildCopilotHook,Ct as buildCopilotHooks,_t as buildCursorHook,yt as buildCursorHooks,vt as buildGeminiHook,Kt as buildGeminiHooks,io as buildPluginHooksJson,St as buildPreToolUseHook,pt as buildSessionStartHook,ft as buildStopHook,lt as buildUserPromptSubmitHook,K as hookBuendelQuelle,to as installAmbientHooks,ro as installCodexHooks,eo as installCopilotHooks,oo as installCursorHooks,no as installGeminiHooks,Ot as mergeAmbientSettings,jt as mergeCodexHooks,Nt as mergeCopilotHooks,Et as mergeCursorHooks,Jt as mergeGeminiHooks};
1
+ import{existsSync as w,readFileSync as j}from"node:fs";import{readFile as v,writeFile as E,chmod as M,mkdir as N}from"node:fs/promises";import{dirname as K,resolve as l}from"node:path";import{fileURLToPath as nt}from"node:url";import{CURSOR_FLAG as rt}from"./cursor-hook.js";import{COPILOT_FLAG as st,COPILOT_HOOK_EVENTS as it}from"./copilot-hook.js";import{CODEX_FLAG as ct,CODEX_HOOK_EVENTS as at}from"./codex-hook.js";import{GEMINI_FLAG as ut,GEMINI_HOOK_EVENTS as pt}from"./gemini-hook.js";import{istCachlyEintrag as J}from"./hook-zugang.js";const B="v5",oo="ambient-recall",S="cachly-ambient-einblendung.mjs";function C(t){return t.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}function I(t,o){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${B}`,"// Pushes relevant memory into context automatically. Cross-platform Node hook","// (no shell script \u2014 runs identically on Windows/macOS/Linux). Never blocks","// the agent: every failure path exits 0 with no output (graceful degrade).",`// Runs the hook bundle next to this file (${S}) in this process.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${C(o.instanceId)}';`,`process.env.CACHLY_HOOK_EVENT = '${C(t)}';`,`process.argv.splice(2, process.argv.length, '${C(t)}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
2
+ `)}const mt="__CACHLY_EREIGNIS__",lt="__CACHLY_INSTANZ__",eo="cachly-ambient-vorlage.mjs";function no(){return I(mt,{instanceId:lt})}function V(){const t=K(nt(import.meta.url));for(const o of[l(t,"..",L,S),l(t,"..","..",L,S)])if(w(o))return o;return null}function St(t){return I("SessionStart",t)}function ft(t){return I("UserPromptSubmit",t)}function ht(t){return I("PreToolUse",t)}function dt(t){return I("Stop",t)}const bt={SessionStart:30,UserPromptSubmit:10,PreToolUse:10,Stop:60},gt="Edit|Write|MultiEdit|NotebookEdit";function R(t,o){const e=(n,i,p)=>({...p?{matcher:p}:{},hooks:[{type:"command",command:`node "${i}"${o?` ${o(n)}`:""}`,timeout:bt[n]}]}),s={SessionStart:[e("SessionStart",t.sessionStart)],UserPromptSubmit:[e("UserPromptSubmit",t.userPromptSubmit)]};return t.preToolUse&&(s.PreToolUse=[e("PreToolUse",t.preToolUse,gt)]),t.stop&&(s.Stop=[e("Stop",t.stop)]),s}const $=".claude/hooks",Ot=".claude/settings.json",D={SessionStart:"cachly-ambient-session-start.mjs",UserPromptSubmit:"cachly-ambient-prompt-submit.mjs",PreToolUse:"cachly-ambient-pre-tool.mjs",Stop:"cachly-ambient-stop.mjs"},kt=".claude/hooks/cachly-ambient-",ro="cachly-ambient-settings.vorlage.json";function so(){const t=e=>`\${CLAUDE_PROJECT_DIR}/${$}/${D[e]}`,o=R({sessionStart:t("SessionStart"),userPromptSubmit:t("UserPromptSubmit"),preToolUse:t("PreToolUse"),stop:t("Stop")});return`${JSON.stringify(o,null,2)}
3
+ `}function _t(t,o){const e=t.hooks??[];return e.length>0&&e.every(s=>{const n=s.command??"";return n.replace(/\\/g,"/").includes(kt)||o.has(n)||[...o].some(i=>n.includes(`"${i}"`))})}function Et(t,o){const e={...t,hooks:{...t.hooks??{}}},s=e.hooks,n=R(o),i=new Set([o.sessionStart,o.userPromptSubmit,o.preToolUse,o.stop].filter(c=>!!c));for(const[c,r]of Object.entries(n)){const u=(Array.isArray(s[c])?s[c]:[]).filter(f=>!_t(f,i));s[c]=[...u,...r]}const p=JSON.stringify(e)!==JSON.stringify(t);return{settings:e,changed:p}}async function io(t,o,e,s={}){const n=l(t,$),i={instanceId:o,apiKey:e},p=["SessionStart","UserPromptSubmit","PreToolUse","Stop"],c={SessionStart:St(i),UserPromptSubmit:ft(i),PreToolUse:ht(i),Stop:dt(i)},r=a=>l(n,D[a]),u=V();if(!u)throw new Error(`cachly hook bundle ${S} missing from the package`);const f=j(u,"utf-8"),d=l(n,S),k=async a=>{try{return await v(a,"utf-8")}catch{return""}},y=l(t,Ot),T=w(y);let b={};if(T){const a=await k(y);try{const g=a.charCodeAt(0)===65279?a.slice(1):a,_=g.trim()?JSON.parse(g):{};if(!H(_))throw new O("is not a JSON object");if(_.hooks!==void 0&&!H(_.hooks))throw new O('has a "hooks" field that is not an object');b=_}catch(g){const _=g instanceof O?g.message:/^\s*\/\/|\/\*/m.test(a)?"has comments, and cachly only rewrites plain JSON":"is not valid JSON";return{sessionStartPath:r("SessionStart"),promptSubmitPath:r("UserPromptSubmit"),preToolUsePath:r("PreToolUse"),stopPath:r("Stop"),bundlePath:d,scripts:"unchanged",settings:"skipped",grund:_}}}let m=!1,h=await k(d)===f;for(const a of p){const g=await k(r(a));g&&(m=!0),g!==c[a]+`
4
+ `&&(h=!1)}const G=h?"unchanged":m?"upgraded":"written";if(G!=="unchanged"){await N(n,{recursive:!0}),await E(d,f,"utf-8");for(const a of p)await E(r(a),c[a]+`
5
+ `,"utf-8"),await M(r(a),493).catch(()=>{})}const x=a=>s.portable!==!1?`\${CLAUDE_PROJECT_DIR}/${$}/${D[a]}`:r(a),{settings:ot,changed:et}=Et(b,{sessionStart:x("SessionStart"),userPromptSubmit:x("UserPromptSubmit"),preToolUse:x("PreToolUse"),stop:x("Stop")});let P;return T?et?P="merged":P="unchanged":P="written",P!=="unchanged"&&(await N(l(t,".claude"),{recursive:!0}),await E(y,JSON.stringify(ot,null,2)+`
6
+ `,"utf-8")),{sessionStartPath:r("SessionStart"),promptSubmitPath:r("UserPromptSubmit"),preToolUsePath:r("PreToolUse"),stopPath:r("Stop"),bundlePath:d,scripts:G,settings:P}}const F=".cursor/hooks",Tt=".cursor/hooks.json",X="cachly-ambient-cursor.mjs",Pt={sessionStart:30,beforeSubmitPrompt:10,postToolUse:5};function U(t,o,e,s){return["#!/usr/bin/env node",`// cachly Ambient Recall \u2014 ${t} ${B}`,`// Einblendung fuer ${t}: ${e.join(", ")}.`,"// Blockiert nie: jeder Fehler endet mit Exit 0. Ruft das Buendel daneben",`// (${S}) in diesem Prozess.`,`process.env.CACHLY_BRAIN_INSTANCE_ID = '${C(s.instanceId)}';`,`process.argv.push('${o}');`,"try {",` await import('./${S}');`,"} catch {"," process.exit(0);","}"].join(`
7
+ `)}function It(t){return U("Cursor",rt,["sessionStart","beforeSubmitPrompt","postToolUse"],t)}function yt(){const t=o=>[{command:`node ${F}/${X} ${o}`,timeout:Pt[o]}];return{sessionStart:t("sessionStart"),beforeSubmitPrompt:t("beforeSubmitPrompt"),postToolUse:t("postToolUse")}}function xt(t){return Y(t,yt())}function Y(t,o){const e={...t.hooks??{}};for(const[n,i]of Object.entries(o)){Z(e[n],n);const p=(e[n]??[]).filter(c=>!J(c));e[n]=[...p,...i]}const s={...t,version:typeof t.version=="number"?t.version:1,hooks:e};return{datei:s,changed:JSON.stringify(s)!==JSON.stringify(t)}}function z(t,o){const e={...t.hooks??{}};for(const[n,i]of Object.entries(o)){Z(e[n],n);const p=(e[n]??[]).flatMap(c=>{const r=c?.hooks;if(!Array.isArray(r))return[c];const u=r.filter(f=>!J(f));return u.length===r.length?[c]:u.length?[{...c,hooks:u}]:[]});e[n]=[...p,...i]}const s={...t,hooks:e};return{datei:s,changed:JSON.stringify(s)!==JSON.stringify(t)}}async function A(t){const o=l(t.projectDir,t.hookDir),e=V();if(!e)throw new Error(`cachly hook bundle ${S} missing from the package`);const s=j(e,"utf-8"),n=l(o,S),i=l(o,t.skriptName),p=t.skript+`
8
+ `,c=async m=>{try{return await v(m,"utf-8")}catch{return""}},r=l(t.projectDir,t.configDatei),u=w(r)?await c(r):"",f=!u.trim();let d;try{const m=u.charCodeAt(0)===65279?u.slice(1):u,h=f?{}:JSON.parse(m);if(!H(h))throw new O("is not a JSON object");if(h.hooks!==void 0&&!H(h.hooks))throw new O('has a "hooks" field that is not an object');d=t.merge(h,i)}catch(m){const h=m instanceof O?m.message:/^\s*\/\/|\/\*/m.test(u)?"has comments, and cachly only rewrites plain JSON":"is not valid JSON";return{scriptPath:i,bundlePath:n,hooksPath:r,scripts:"unchanged",hooks:"skipped",grund:h}}await N(o,{recursive:!0});const k=await c(i),T=k===p&&await c(n)===s?"unchanged":k?"upgraded":"written";T!=="unchanged"&&(await E(n,s,"utf-8"),await E(i,p,"utf-8"),await M(i,493).catch(()=>{}));let b;if(f?b="written":d.changed?b="merged":b="unchanged",b!=="unchanged"){const m=/^([ \t]+)"/m.exec(u)?.[1]??2;await N(K(r),{recursive:!0}),await E(r,JSON.stringify(d.datei,null,m)+`
9
+ `,"utf-8")}return{scriptPath:i,bundlePath:n,hooksPath:r,scripts:T,hooks:b}}function H(t){return!!t&&typeof t=="object"&&!Array.isArray(t)}class O extends Error{}function Z(t,o){if(t!==void 0&&!Array.isArray(t))throw new O(`has a "hooks.${o}" entry that is not a list`)}async function co(t,o){return A({projectDir:t,hookDir:F,skriptName:X,skript:It({instanceId:o}),configDatei:Tt,merge:e=>xt(e)})}const W=".github/hooks",Nt=".github/hooks/cachly-ambient.json",Q="cachly-ambient-copilot.mjs",Ct={sessionStart:30,userPromptSubmitted:10,postToolUse:5};function Ut(t){return U("VS Code / Copilot",st,it,t)}function At(){const t=o=>[{type:"command",command:`node ${W}/${Q} ${o}`,cwd:".",timeoutSec:Ct[o]}];return{sessionStart:t("sessionStart"),userPromptSubmitted:t("userPromptSubmitted"),postToolUse:t("postToolUse")}}function Ht(t){return Y(t,At())}async function ao(t,o){return A({projectDir:t,hookDir:W,skriptName:Q,skript:Ut({instanceId:o}),configDatei:Nt,merge:e=>Ht(e)})}const wt=".codex/hooks",Rt=".codex/hooks.json",$t="cachly-ambient-codex.mjs",Dt={SessionStart:30,UserPromptSubmit:10};function Lt(t){return U("Codex",ct,at,t)}function Gt(t){const o=e=>[{hooks:[{type:"command",command:`node "${t}" ${e}`,timeout:Dt[e]}]}];return{SessionStart:o("SessionStart"),UserPromptSubmit:o("UserPromptSubmit")}}function jt(t,o){return z(t,Gt(o))}async function uo(t,o){return A({projectDir:t,hookDir:wt,skriptName:$t,skript:Lt({instanceId:o}),configDatei:Rt,merge:(e,s)=>jt(e,s)})}const q=".gemini/hooks",vt=".gemini/settings.json",tt="cachly-ambient-gemini.mjs",Mt={SessionStart:3e4,BeforeAgent:1e4},Kt={SessionStart:"cachly-briefing",BeforeAgent:"cachly-recall"};function Jt(t){return U("Gemini CLI",ut,pt,t)}function Bt(){const t=o=>[{hooks:[{name:Kt[o],type:"command",command:`node ${q}/${tt} ${o}`,timeout:Mt[o]}]}];return{SessionStart:t("SessionStart"),BeforeAgent:t("BeforeAgent")}}function Vt(t){return z(t,Bt())}async function po(t,o){return A({projectDir:t,hookDir:q,skriptName:tt,skript:Jt({instanceId:o}),configDatei:vt,merge:e=>Vt(e)})}const mo=["SessionStart","UserPromptSubmit","Stop"],L="hooks";function lo(){const t=`\${CLAUDE_PLUGIN_ROOT}/${L}/${S}`,o=R({sessionStart:t,userPromptSubmit:t,stop:t},e=>`${e} --plugin`);return JSON.stringify({hooks:o},null,2)+`
10
+ `}export{oo as AMBIENT_CLI_SUBCOMMAND,B as AMBIENT_HOOK_VERSION,$ as CLAUDE_HOOK_DIR,Ot as CLAUDE_SETTINGS_DATEI,Rt as CODEX_HOOKS_DATEI,wt as CODEX_HOOK_DIR,$t as CODEX_SKRIPT,Dt as CODEX_TIMEOUTS,Nt as COPILOT_HOOKS_DATEI,W as COPILOT_HOOK_DIR,Q as COPILOT_SKRIPT,Ct as COPILOT_TIMEOUTS,Tt as CURSOR_HOOKS_DATEI,F as CURSOR_HOOK_DIR,X as CURSOR_SKRIPT,Pt as CURSOR_TIMEOUTS,q as GEMINI_HOOK_DIR,vt as GEMINI_SETTINGS_DATEI,tt as GEMINI_SKRIPT,Mt as GEMINI_TIMEOUTS_MS,S as HOOK_BUENDEL,eo as HOOK_VORLAGE,L as PLUGIN_HOOK_DIR,mo as PLUGIN_HOOK_EVENTS,gt as PRE_TOOL_USE_MATCHER,ro as SETTINGS_VORLAGE,mt as VORLAGE_EREIGNIS,lt as VORLAGE_INSTANZ,no as buildAmbientHookVorlage,R as buildAmbientSettingsHooks,so as buildAmbientSettingsVorlage,Lt as buildCodexHook,Gt as buildCodexHooks,Ut as buildCopilotHook,At as buildCopilotHooks,It as buildCursorHook,yt as buildCursorHooks,Jt as buildGeminiHook,Bt as buildGeminiHooks,lo as buildPluginHooksJson,ht as buildPreToolUseHook,St as buildSessionStartHook,dt as buildStopHook,ft as buildUserPromptSubmitHook,V as hookBuendelQuelle,io as installAmbientHooks,uo as installCodexHooks,ao as installCopilotHooks,co as installCursorHooks,po as installGeminiHooks,Et as mergeAmbientSettings,jt as mergeCodexHooks,Ht as mergeCopilotHooks,xt as mergeCursorHooks,Vt as mergeGeminiHooks};
@@ -1,13 +1,13 @@
1
- import{zeitpunkt as A}from"./zeitmessung.js";const i={apiUrl:process.env.CACHLY_API_URL??"https://api.cachly.dev",jwt:process.env.CACHLY_JWT??"",model:process.env.CACHLY_EMBED_MODEL??""};function R(r){i.jwt=r,r&&!I&&d==="none"&&(d="cachly")}const h=Number(process.env.CACHLY_EMBED_TIMEOUT_MS??8e3),p=Number(process.env.CACHLY_EMBED_TIMEOUT_MAX_MS??45e3),g=12;function f(r,n){return n==="kurz"?h:Math.min(p,h+r.length*g)}function b(){return process.env.CACHLY_JWT?"cachly":process.env.OLLAMA_BASE_URL?"ollama":"none"}const I=!!process.env.CACHLY_EMBED_PROVIDER;let d=(process.env.CACHLY_EMBED_PROVIDER??b()).toLowerCase();async function y(r,n,s){const c=f(r,n);switch(d){case"cachly":{if(!i.jwt)throw new Error(`CACHLY_JWT not set.
1
+ import{zeitpunkt as A}from"./zeitmessung.js";const a={apiUrl:process.env.CACHLY_API_URL??"https://api.cachly.dev",jwt:process.env.CACHLY_JWT??"",model:process.env.CACHLY_EMBED_MODEL??""};function H(t){a.jwt=t,t&&!C&&d==="none"&&(d="cachly")}const p=Number(process.env.CACHLY_EMBED_TIMEOUT_MS??8e3),b=Number(process.env.CACHLY_EMBED_TIMEOUT_MAX_MS??45e3),w=12;function I(t,e){return e==="kurz"?p:Math.min(b,p+t.length*w)}function y(){return process.env.CACHLY_JWT?"cachly":process.env.OLLAMA_BASE_URL?"ollama":"none"}const C=!!process.env.CACHLY_EMBED_PROVIDER;let d=(process.env.CACHLY_EMBED_PROVIDER??y()).toLowerCase();async function g(t,e,r){const i=I(t,e);switch(d){case"cachly":{if(!a.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:
5
5
  openai \u2192 OPENAI_API_KEY
6
6
  gemini \u2192 GEMINI_API_KEY
7
- ollama \u2192 OLLAMA_BASE_URL (local, no key needed)`);const e=`${i.apiUrl}/api/v1/embed`,o={text:r};(s??i.model)&&(o.model=s??i.model);const t=process.env.CACHLY_ADMIN_KEY??"",a=await fetch(e,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i.jwt}`,...t?{"X-Admin-Key":t}:{}},body:JSON.stringify(o),signal:AbortSignal.timeout(c)});if(!a.ok){const _=await a.text();let E=null;const m=Number(a.headers.get("retry-after"));if(Number.isFinite(m)&&m>=0)E=m;else try{const u=JSON.parse(_);typeof u.retry_after=="number"&&u.retry_after>=0&&(E=u.retry_after)}catch{}throw Object.assign(new Error(`Cachly embed API error ${a.status}: ${_.slice(0,200)}`),{status:a.status,retryAfterSek:E})}return(await a.json()).embedding}case"mistral":{const e=process.env.MISTRAL_API_KEY;if(!e)throw new Error("MISTRAL_API_KEY not set");const o=i.model!=="text-embedding-3-small"?i.model:"mistral-embed",t=await fetch("https://api.mistral.ai/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:o,input:[r]}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Mistral embedding error: ${t.statusText}`);const a=await t.json();if(!a.data?.[0]?.embedding)throw new Error("Mistral returned empty embedding response");return a.data[0].embedding}case"cohere":{const e=process.env.COHERE_API_KEY;if(!e)throw new Error("COHERE_API_KEY not set");const o=i.model!=="text-embedding-3-small"?i.model:"embed-english-v3.0",t=await fetch("https://api.cohere.com/v2/embed",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${e}`},body:JSON.stringify({model:o,texts:[r],input_type:"search_query",embedding_types:["float"]}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Cohere embedding error: ${t.statusText}`);return(await t.json()).embeddings.float[0]}case"ollama":{const e=process.env.OLLAMA_BASE_URL??"http://localhost:11434",o=s??(i.model!=="text-embedding-3-small"?i.model:"nomic-embed-text"),t=await fetch(`${e}/api/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:o,prompt:r}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Ollama embedding error: ${t.statusText}`);return(await t.json()).embedding}case"gemini":{const e=process.env.GEMINI_API_KEY;if(!e)throw new Error("GEMINI_API_KEY not set");const o=i.model!=="text-embedding-3-small"?i.model:"text-embedding-004",t=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${o}:embedContent?key=${e}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:`models/${o}`,content:{parts:[{text:r}]}}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`Gemini embedding error: ${t.statusText}`);return(await t.json()).embedding.values}case"openai":{const e=process.env.OPENAI_API_KEY;if(!e)throw new Error(`OPENAI_API_KEY not set.
7
+ ollama \u2192 OLLAMA_BASE_URL (local, no key needed)`);const n=`${a.apiUrl}/api/v1/embed`,s={text:t};(r??a.model)&&(s.model=r??a.model);const o=process.env.CACHLY_ADMIN_KEY??"",c=await fetch(n,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${a.jwt}`,...o?{"X-Admin-Key":o}:{},"X-Cachly-Embed-Zweck":e==="kurz"?"suche":"schreiben"},body:JSON.stringify(s),signal:AbortSignal.timeout(i)});if(!c.ok){const h=await c.text();let m=null;const f=c.headers.get("retry-after"),E=f===null?NaN:Number(f);if(Number.isFinite(E)&&E>=0)m=E;else try{const u=JSON.parse(h);typeof u.retry_after=="number"&&u.retry_after>=0&&(m=u.retry_after)}catch{}throw Object.assign(new Error(`Cachly embed API error ${c.status}: ${h.slice(0,200)}`),{status:c.status,retryAfterSek:m})}return(await c.json()).embedding}case"mistral":{const n=process.env.MISTRAL_API_KEY;if(!n)throw new Error("MISTRAL_API_KEY not set");const s=a.model!=="text-embedding-3-small"?a.model:"mistral-embed",o=await fetch("https://api.mistral.ai/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({model:s,input:[t]}),signal:AbortSignal.timeout(i)});if(!o.ok)throw new Error(`Mistral embedding error: ${o.statusText}`);const c=await o.json();if(!c.data?.[0]?.embedding)throw new Error("Mistral returned empty embedding response");return c.data[0].embedding}case"cohere":{const n=process.env.COHERE_API_KEY;if(!n)throw new Error("COHERE_API_KEY not set");const s=a.model!=="text-embedding-3-small"?a.model:"embed-english-v3.0",o=await fetch("https://api.cohere.com/v2/embed",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({model:s,texts:[t],input_type:"search_query",embedding_types:["float"]}),signal:AbortSignal.timeout(i)});if(!o.ok)throw new Error(`Cohere embedding error: ${o.statusText}`);return(await o.json()).embeddings.float[0]}case"ollama":{const n=process.env.OLLAMA_BASE_URL??"http://localhost:11434",s=r??(a.model!=="text-embedding-3-small"?a.model:"nomic-embed-text"),o=await fetch(`${n}/api/embeddings`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:s,prompt:t}),signal:AbortSignal.timeout(i)});if(!o.ok)throw new Error(`Ollama embedding error: ${o.statusText}`);return(await o.json()).embedding}case"gemini":{const n=process.env.GEMINI_API_KEY;if(!n)throw new Error("GEMINI_API_KEY not set");const s=a.model!=="text-embedding-3-small"?a.model:"text-embedding-004",o=await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${s}:embedContent?key=${n}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({model:`models/${s}`,content:{parts:[{text:t}]}}),signal:AbortSignal.timeout(i)});if(!o.ok)throw new Error(`Gemini embedding error: ${o.statusText}`);return(await o.json()).embedding.values}case"openai":{const n=process.env.OPENAI_API_KEY;if(!n)throw new Error(`OPENAI_API_KEY not set.
8
8
 
9
9
  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
- CACHLY_EMBED_PROVIDER=cachly (server-side, no key needed)`);const o=i.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:r}),signal:AbortSignal.timeout(c)});if(!t.ok)throw new Error(`OpenAI embedding error: ${t.statusText}`);const a=await t.json();if(!a.data?.[0]?.embedding)throw new Error("OpenAI returned empty embedding response");return a.data[0].embedding}default:throw new Error(`Unknown CACHLY_EMBED_PROVIDER="${d}".
13
- Supported: cachly (default), openai, mistral, cohere, ollama, gemini`)}}const w=3,C=4;function M(r){const n=r;if(typeof n?.status=="number")return n.status===429||n.status>=500;if(n?.name==="TimeoutError"||n?.name==="AbortError")return!1;if(/fetch failed/i.test(String(n?.message??"")))return!0;const s=n?.cause?.code??"";return["ECONNRESET","ECONNREFUSED","ETIMEDOUT","EAI_AGAIN","EPIPE","UND_ERR_SOCKET"].includes(s)}function O(r,n,s){if(n>=(s==="lang"?C:w)||!M(r))return null;const e=r?.retryAfterSek;if(typeof e=="number"&&Number.isFinite(e)&&e>=0){const o=e*1e3;return s==="kurz"?o<=2e3?o:null:Math.min(o,61e3)}return s==="lang"?Math.min(1e3*2**(n-1),8e3):250*2**(n-1)}function N(r,n){const s=`${n?.modell??""}\0${n?.geduld??"kurz"}\0${r}`,c=Date.now(),e=l.get(s);if(e&&e.bis>c)return e.vektor;const o=T(r,n);if(l.set(s,{bis:c+P,vektor:o}),l.size>v){const t=l.keys().next().value;t!==void 0&&l.delete(t)}return o.catch(()=>{l.get(s)?.vektor===o&&l.delete(s)}),o}const P=6e4,v=200,l=new Map;function Y(){l.clear()}async function T(r,n){const s=n?.geduld??"kurz";if(n?.modell&&d!=="cachly"&&d!=="ollama")throw new Error(`Anbieter "${d}" kann kein abweichendes Modell anfragen (verlangt: ${n.modell}).`);let c=0;for(;;){c++;try{A(`einbettung: Anfang (${r.length} Zeichen, Versuch ${c})`);const e=await y(r,s,n?.modell);return A("einbettung: fertig"),e}catch(e){const o=O(e,c,s);if(o===null)throw e;await new Promise(t=>setTimeout(t,o))}}}function k(){switch(d){case"cachly":return!!i.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 D(){const r={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(d==="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 n=r[d]??"CACHLY_JWT";return`CACHLY_EMBED_PROVIDER=${d} \u2192 requires ${n}`}export{d as EMBED_PROVIDER,N as computeEmbedding,i as embedConfig,D as embedProviderHint,k as hasEmbedProvider,M as istVoruebergehend,R as setEmbedJwt,Y as vergissEinbettungen,O as wiederholungMs,f as zeitlimitMs};
12
+ CACHLY_EMBED_PROVIDER=cachly (server-side, no key needed)`);const s=a.model||"text-embedding-3-small",o=await fetch("https://api.openai.com/v1/embeddings",{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify({model:s,input:t}),signal:AbortSignal.timeout(i)});if(!o.ok)throw new Error(`OpenAI embedding error: ${o.statusText}`);const c=await o.json();if(!c.data?.[0]?.embedding)throw new Error("OpenAI returned empty embedding response");return c.data[0].embedding}default:throw new Error(`Unknown CACHLY_EMBED_PROVIDER="${d}".
13
+ Supported: cachly (default), openai, mistral, cohere, ollama, gemini`)}}const M=3,P=4;function S(t){const e=t;if(typeof e?.status=="number")return e.status===429||e.status>=500;if(e?.name==="TimeoutError"||e?.name==="AbortError")return!1;if(/fetch failed/i.test(String(e?.message??"")))return!0;const r=e?.cause?.code??"";return["ECONNRESET","ECONNREFUSED","ETIMEDOUT","EAI_AGAIN","EPIPE","UND_ERR_SOCKET"].includes(r)}function L(t,e,r){if(e>=(r==="lang"?P:M)||!S(t))return null;const n=t?.retryAfterSek;if(typeof n=="number"&&Number.isFinite(n)&&n>=0){const s=n*1e3;return r==="kurz"?s<=2e3?s:null:Math.min(s,61e3)}return r==="lang"?Math.min(1e3*2**(e-1),8e3):250*2**(e-1)}const O=Math.max(1,Number(process.env.CACHLY_EMBED_SCHREIB_PARALLEL??4)||4),_=new Map;async function v(t,e){let r=_.get(t);r||(r={laufend:0,warte:[]},_.set(t,r)),r.laufend<O?r.laufend++:await new Promise(i=>r.warte.push(i));try{return await e()}finally{const i=r.warte.shift();i?i():r.laufend--}}function B(t=""){const e=_.get(t);return{laufend:e?.laufend??0,wartend:e?.warte.length??0}}function D(t,e){const r=`${e?.modell??""}\0${e?.geduld??"kurz"}\0${t}`,i=Date.now(),n=l.get(r);if(n&&n.bis>i)return n.vektor;const s=N(t,e);if(l.set(r,{bis:i+T,vektor:s}),l.size>R){const o=l.keys().next().value;o!==void 0&&l.delete(o)}return s.catch(()=>{l.get(r)?.vektor===s&&l.delete(r)}),s}const T=6e4,R=200,l=new Map;function K(){l.clear()}async function N(t,e){const r=e?.geduld??"kurz";if(e?.modell&&d!=="cachly"&&d!=="ollama")throw new Error(`Anbieter "${d}" kann kein abweichendes Modell anfragen (verlangt: ${e.modell}).`);if(t.trim()==="")throw new Error("nothing to embed: empty text");let i=0;for(;;){i++;try{A(`einbettung: Anfang (${t.length} Zeichen, Versuch ${i})`);const n=r==="lang"?await v(e?.modell??"",()=>g(t,r,e?.modell)):await g(t,r,e?.modell);return A("einbettung: fertig"),n}catch(n){const s=L(n,i,r);if(s===null)throw n;await new Promise(o=>setTimeout(o,s))}}}function j(){switch(d){case"cachly":return!!a.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 $(){const t={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(d==="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 e=t[d]??"CACHLY_JWT";return`CACHLY_EMBED_PROVIDER=${d} \u2192 requires ${e}`}export{d as EMBED_PROVIDER,D as computeEmbedding,a as embedConfig,$ as embedProviderHint,j as hasEmbedProvider,S as istVoruebergehend,B as schreibSchlange,H as setEmbedJwt,K as vergissEinbettungen,L as wiederholungMs,I as zeitlimitMs};