context-mode 1.0.91 → 1.0.92

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.
@@ -6,14 +6,14 @@
6
6
  },
7
7
  "metadata": {
8
8
  "description": "Claude Code plugins by Mert Koseoğlu",
9
- "version": "1.0.91"
9
+ "version": "1.0.92"
10
10
  },
11
11
  "plugins": [
12
12
  {
13
13
  "name": "context-mode",
14
14
  "source": "./",
15
15
  "description": "Claude Code MCP plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
16
- "version": "1.0.91",
16
+ "version": "1.0.92",
17
17
  "author": {
18
18
  "name": "Mert Koseoğlu"
19
19
  },
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.91",
3
+ "version": "1.0.92",
4
4
  "description": "MCP server that saves 98% of your context window with session continuity. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and automatic state restore across compactions.",
5
5
  "author": {
6
6
  "name": "Mert Koseoğlu",
@@ -3,7 +3,7 @@
3
3
  "name": "Context Mode",
4
4
  "kind": "tool",
5
5
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
6
- "version": "1.0.91",
6
+ "version": "1.0.92",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.91",
3
+ "version": "1.0.92",
4
4
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
5
5
  "author": {
6
6
  "name": "Mert Koseoğlu",
@@ -163,15 +163,15 @@ export class AnalyticsEngine {
163
163
  total_savings_ratio: totalSavingsRatio,
164
164
  };
165
165
  }
166
- // ── Continuity data ──
167
- const eventTotal = this.db.prepare("SELECT COUNT(*) as cnt FROM session_events").get().cnt;
168
- const byCategory = this.db.prepare("SELECT category, COUNT(*) as cnt FROM session_events GROUP BY category ORDER BY cnt DESC").all();
169
- const meta = this.db.prepare("SELECT compact_count FROM session_meta ORDER BY started_at DESC LIMIT 1").get();
166
+ // ── Continuity data (scoped to current session) ──
167
+ const eventTotal = this.db.prepare("SELECT COUNT(*) as cnt FROM session_events WHERE session_id = ?").get(sid).cnt;
168
+ const byCategory = this.db.prepare("SELECT category, COUNT(*) as cnt FROM session_events WHERE session_id = ? GROUP BY category ORDER BY cnt DESC").all(sid);
169
+ const meta = this.db.prepare("SELECT compact_count FROM session_meta WHERE session_id = ?").get(sid);
170
170
  const compactCount = meta?.compact_count ?? 0;
171
- const resume = this.db.prepare("SELECT event_count, consumed FROM session_resume ORDER BY created_at DESC LIMIT 1").get();
171
+ const resume = this.db.prepare("SELECT event_count, consumed FROM session_resume WHERE session_id = ? ORDER BY created_at DESC LIMIT 1").get(sid);
172
172
  const resumeReady = resume ? !resume.consumed : false;
173
- // Build category previews
174
- const previewRows = this.db.prepare("SELECT category, type, data FROM session_events ORDER BY id DESC").all();
173
+ // Build category previews (current session only)
174
+ const previewRows = this.db.prepare("SELECT category, type, data FROM session_events WHERE session_id = ? ORDER BY id DESC").all(sid);
175
175
  const previews = new Map();
176
176
  for (const row of previewRows) {
177
177
  if (!previews.has(row.category))
package/cli.bundle.mjs CHANGED
@@ -338,7 +338,7 @@ ${n}
338
338
  stderr:
339
339
  ${o}`}}var wk=v(()=>{"use strict"});import{execFileSync as xj}from"node:child_process";function vj(){if(process.platform==="win32")return NaN;let t=process.ppid;if(!t||t<=1)return NaN;try{let e=xj("ps",["-o","ppid=","-p",String(t)],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).trim(),r=parseInt(e,10);return Number.isFinite(r)?r:NaN}catch{return NaN}}function Sj(t={}){let e=t.getPpid??(()=>process.ppid),r=t.readGrandparentPpid??vj,n=e(),o=r();return()=>{let s=e();return!(s!==n||s===0||s===1||!Number.isNaN(o)&&o>1&&r()===1)}}function $k(t){let e=t.checkIntervalMs??3e4,r=t.isParentAlive??bj,n=!1,o=()=>{n||(n=!0,t.onShutdown())},s=setInterval(()=>{r()||o()},e);s.unref();let i=["SIGTERM","SIGINT"];process.platform!=="win32"&&i.push("SIGHUP");for(let a of i)process.on(a,o);return()=>{n=!0,clearInterval(s);for(let a of i)process.removeListener(a,o)}}var bj,Ek=v(()=>{"use strict";bj=Sj()});import{createHash as kj}from"node:crypto";import{execFileSync as wj}from"node:child_process";function zh(){let t=process.env.CONTEXT_MODE_SESSION_SUFFIX;if(t!==void 0)return t?`__${t}`:"";try{let e=process.cwd(),r=wj("git",["worktree","list","--porcelain"],{encoding:"utf-8",timeout:2e3,stdio:["ignore","pipe","ignore"]}).split(/\r?\n/).find(n=>n.startsWith("worktree "))?.replace("worktree ","")?.trim();if(r&&e!==r)return`__${kj("sha256").update(e).digest("hex").slice(0,8)}`}catch{}return""}var Tk=v(()=>{"use strict";gi()});function $j(t,e){let r=t.split(".").map(Number),n=e.split(".").map(Number);for(let o=0;o<3;o++){if((r[o]??0)>(n[o]??0))return!0;if((r[o]??0)<(n[o]??0))return!1}return!1}function Go(t){return t>=1024*1024?`${(t/1024/1024).toFixed(1)} MB`:t>=1024?`${(t/1024).toFixed(1)} KB`:`${Math.round(t)} B`}function Pj(t){let e=parseFloat(t);if(isNaN(e)||e<1)return"< 1 min";if(e<60)return`${Math.round(e)} min`;let r=Math.floor(e/60),n=Math.round(e%60);return n>0?`${r}h ${n}m`:`${r}h`}function jh(t){return t>=1e6?`${(t/1e6).toFixed(1)}M`:t>=1e3?`${(t/1e3).toFixed(1)}K`:String(t)}function Pk(t,e,r=40){if(e<=0)return"\u2591".repeat(r);let n=Math.max(1,Math.round(t/e*r));return"\u2588".repeat(Math.min(n,r))+"\u2591".repeat(Math.max(0,r-n))}function Vc(t,e,r){let n=[],o=Pj(t.session.uptime_min),s=t.savings.kept_out+(t.cache?t.cache.bytes_saved:0),i=t.savings.total_bytes_returned,a=t.savings.total_calls,c=s+i,u=c>0?s/c*100:0,l=Math.round(s/4);if(s===0){n.push(`context-mode ${o} ${a} calls`),n.push(""),a===0?n.push("No tool calls yet. Use batch_execute or execute to start saving tokens."):n.push(`${Go(i)} entered context | 0 tokens saved`),n.push("");let p=e?`v${e}`:"context-mode";return n.push(p),e&&r&&r!=="unknown"&&$j(r,e)&&n.push(`Update available: v${e} -> v${r} | ctx_upgrade`),n.join(`
340
340
  `)}n.push(`${jh(l)} tokens saved \xB7 ${u.toFixed(1)}% reduction \xB7 ${o}`),n.push(""),n.push(`Without context-mode |${Pk(c,c)}| ${Go(c)}`),n.push(`With context-mode |${Pk(i,c)}| ${Go(i)}`),n.push(""),n.push(`${Go(s)} kept out of your conversation. Never entered context.`),n.push("");let d=[`${a} calls`];t.cache&&t.cache.hits>0&&d.push(`${t.cache.hits} cache hits (+${Go(t.cache.bytes_saved)})`),n.push(d.join(" \xB7 "));let m=t.savings.by_tool.filter(p=>p.calls>0);if(m.length>=2){n.push("");let p=m.map(f=>{let g=f.context_kb*1024,_=u<100?g/(1-u/100):g,y=Math.max(0,_-g);return{...f,returnedBytes:g,estimatedSaved:y}}).sort((f,g)=>g.estimatedSaved-f.estimatedSaved);for(let f of p){let g=f.tool.length>22?f.tool.slice(0,19)+"...":f.tool;n.push(` ${g.padEnd(22)} ${String(f.calls).padStart(4)} calls ${Go(f.estimatedSaved).padStart(8)} saved`)}}if(t.continuity.total_events>0){n.push("");let p=t.continuity.by_category,f=[],g=p.find(Z=>Z.category==="file")?.count,_=p.find(Z=>Z.category==="git")?.count,y=p.find(Z=>Z.category==="prompt")?.count,x=p.find(Z=>Z.category==="error")?.count,k=p.find(Z=>Z.category==="task")?.count;g&&f.push(`${g} files`),_&&f.push(`${_} git ops`),y&&f.push(`${y} prompts`),x&&f.push(`${x} errors`),k&&f.push(`${k} tasks`);let T=f.length>0?` \xB7 ${f.join(", ")}`:"";t.continuity.compact_count>0?(n.push(`${jh(t.continuity.total_events)} events remembered across ${t.continuity.compact_count} compaction${t.continuity.compact_count!==1?"s":""}${T}`),n.push("Zero knowledge lost \u2014 picks up exactly where you left off.")):n.push(`${jh(t.continuity.total_events)} events tracked${T}`)}n.push("");let h=e?`v${e}`:"context-mode";return n.push(h),e&&r&&r!=="unknown"&&r!==e&&n.push(`Update available: v${e} -> v${r} | ctx_upgrade`),n.join(`
341
- `)}var Ej,Tj,Ko,Rk=v(()=>{"use strict";Ej={file:"Files tracked",rule:"Project rules (CLAUDE.md)",prompt:"Your requests saved",mcp:"Plugin tools used",git:"Git operations",env:"Environment setup",error:"Errors caught",task:"Tasks in progress",decision:"Your decisions",cwd:"Working directory",skill:"Skills used",subagent:"Delegated work",intent:"Session mode",data:"Data references",role:"Behavioral directives"},Tj={file:"Restored after compact \u2014 no need to re-read",rule:"Your project instructions survive context resets",prompt:"Continues exactly where you left off",decision:"Applied automatically \u2014 won\u2019t ask again",task:"Picks up from where it stopped",error:"Tracked and monitored across compacts",git:"Branch, commit, and repo state preserved",env:"Runtime config carried forward",mcp:"Tool usage patterns remembered",subagent:"Delegation history preserved",skill:"Skill invocations tracked"},Ko=class{db;constructor(e){this.db=e}static contextSavingsTotal(e,r){let n=e-r,o=e>0?Math.round(n/e*1e3)/10:0;return{rawBytes:e,contextBytes:r,savedBytes:n,savedPercent:o}}static thinkInCodeComparison(e,r){let n=r>0?Math.round(e/r*10)/10:0;return{fileBytes:e,outputBytes:r,ratio:n}}static toolSavings(e){return e.map(r=>({...r,savedBytes:r.rawBytes-r.contextBytes}))}static sandboxIO(e,r){return{inputBytes:e,outputBytes:r}}queryAll(e){let n=this.db.prepare("SELECT session_id FROM session_meta ORDER BY started_at DESC LIMIT 1").get()?.session_id??"",o=Object.values(e.bytesReturned).reduce((N,Re)=>N+Re,0),s=Object.values(e.calls).reduce((N,Re)=>N+Re,0),i=e.bytesIndexed+e.bytesSandboxed,a=i+o,c=a/Math.max(o,1),u=a>0?Math.round((1-o/a)*100):0,l=new Set([...Object.keys(e.calls),...Object.keys(e.bytesReturned)]),d=Array.from(l).sort().map(N=>({tool:N,calls:e.calls[N]||0,context_kb:Math.round((e.bytesReturned[N]||0)/1024*10)/10,tokens:Math.round((e.bytesReturned[N]||0)/4)})),h=((Date.now()-e.sessionStart)/6e4).toFixed(1),p;if(e.cacheHits>0||e.cacheBytesSaved>0){let N=a+e.cacheBytesSaved,Re=N/Math.max(o,1),de=Math.max(0,24-Math.floor((Date.now()-e.sessionStart)/(3600*1e3)));p={hits:e.cacheHits,bytes_saved:e.cacheBytesSaved,ttl_hours_left:de,total_with_cache:N,total_savings_ratio:Re}}let f=this.db.prepare("SELECT COUNT(*) as cnt FROM session_events").get().cnt,g=this.db.prepare("SELECT category, COUNT(*) as cnt FROM session_events GROUP BY category ORDER BY cnt DESC").all(),y=this.db.prepare("SELECT compact_count FROM session_meta ORDER BY started_at DESC LIMIT 1").get()?.compact_count??0,x=this.db.prepare("SELECT event_count, consumed FROM session_resume ORDER BY created_at DESC LIMIT 1").get(),k=x?!x.consumed:!1,T=this.db.prepare("SELECT category, type, data FROM session_events ORDER BY id DESC").all(),Z=new Map;for(let N of T){Z.has(N.category)||Z.set(N.category,new Set);let Re=Z.get(N.category);if(Re.size<5){let de=N.data;N.category==="file"?de=N.data.split("/").pop()||N.data:N.category==="prompt"&&(de=de.length>50?de.slice(0,47)+"...":de),de.length>40&&(de=de.slice(0,37)+"..."),Re.add(de)}}let V=g.map(N=>({category:N.category,count:N.cnt,label:Ej[N.category]||N.category,preview:Z.get(N.category)?Array.from(Z.get(N.category)).join(", "):"",why:Tj[N.category]||"Survives context resets"}));return{savings:{processed_kb:Math.round(a/1024*10)/10,entered_kb:Math.round(o/1024*10)/10,saved_kb:Math.round(i/1024*10)/10,pct:u,savings_ratio:Math.round(c*10)/10,by_tool:d,total_calls:s,total_bytes_returned:o,kept_out:i,total_processed:a},cache:p,session:{id:n,uptime_min:h},continuity:{total_events:f,by_category:V,compact_count:y,resume_ready:k}}}}});var Uk={};je(Uk,{extractSnippet:()=>Wh,formatBatchQueryResults:()=>Fk,positionsFromHighlight:()=>Lk});import{createRequire as zk}from"node:module";import{createHash as Rj}from"node:crypto";import{existsSync as ot,unlinkSync as Xr,readdirSync as Oj,readFileSync as jk,writeFileSync as Mk,rmSync as Fh,mkdirSync as Uh,cpSync as Cj,statSync as Ok}from"node:fs";import{execSync as Yr}from"node:child_process";import{join as xe,dirname as Qr,resolve as kr}from"node:path";import{fileURLToPath as Ij}from"node:url";import{homedir as Hh,tmpdir as qh}from"node:os";import{request as Aj}from"node:https";function Nj(t){try{let e=Bn();if(!ot(e))return;let r=Oj(e).filter(n=>n.endsWith("-events.md"));for(let n of r){let o=xe(e,n);try{t.index({path:o,source:"session-events"}),Xr(o)}catch{}}}catch{}}function Bn(){if(Kc)return Kc.getSessionDir();let t=xe(Hh(),".claude","context-mode","sessions");return Uh(t,{recursive:!0}),t}function zj(){return process.env.CLAUDE_PROJECT_DIR||process.env.GEMINI_PROJECT_DIR||process.env.VSCODE_CWD||process.env.OPENCODE_PROJECT_DIR||process.env.PI_PROJECT_DIR||process.env.CONTEXT_MODE_PROJECT_DIR||process.cwd()}function Jc(){let e=zj().replace(/\\/g,"/");return Rj("sha256").update(e).digest("hex").slice(0,16)}function Zh(){let t=Jc(),e=Bn(),r=xe(Qr(e),"content");return Uh(r,{recursive:!0}),xe(r,`${t}.db`)}function Vn(){if(!cr){let t=Zh();cr=new Bc(t);try{let e=Qr(Zh());Oh(e,14),cr.cleanupStaleSources(14);let r=xe(Hh(),".context-mode","content");ot(r)&&Oh(r,0)}catch{}Rh()}return Nj(cr),cr}async function Dj(){return new Promise(t=>{let e=Aj("https://registry.npmjs.org/context-mode/latest",{headers:{Connection:"close"}},r=>{let n="";r.on("data",o=>{n+=o}),r.on("end",()=>{try{let o=JSON.parse(n);t(o.version??"unknown")}catch{t("unknown")}})});e.on("error",()=>t("unknown")),e.setTimeout(5e3,()=>{e.destroy(),t("unknown")}),e.end()})}function Lj(){let t=Kc?.name;return t==="Claude Code"?"/ctx-upgrade":t==="OpenClaw"?"npm run install:openclaw":t==="Pi"?"npm run build":"npm update -g context-mode"}function Fj(t,e){let r=t.split(".").map(Number),n=e.split(".").map(Number);for(let o=0;o<3;o++){if((r[o]??0)>(n[o]??0))return!0;if((r[o]??0)<(n[o]??0))return!1}return!1}function Zj(){return!tn||tn==="unknown"?!1:Fj(tn,en)}function Uj(){if(!Zj())return!1;let t=Date.now();if(Wc>=jj){if(t-Ck<Mj)return!1;Wc=0}return Wc===0&&(Ck=t),Wc++,!0}function H(t,e){if(Uj()&&e.content.length>0){let n=Lj();e.content[0].text=`\u26A0\uFE0F context-mode v${en} outdated \u2192 v${tn} available. Upgrade: ${n}
341
+ `)}var Ej,Tj,Ko,Rk=v(()=>{"use strict";Ej={file:"Files tracked",rule:"Project rules (CLAUDE.md)",prompt:"Your requests saved",mcp:"Plugin tools used",git:"Git operations",env:"Environment setup",error:"Errors caught",task:"Tasks in progress",decision:"Your decisions",cwd:"Working directory",skill:"Skills used",subagent:"Delegated work",intent:"Session mode",data:"Data references",role:"Behavioral directives"},Tj={file:"Restored after compact \u2014 no need to re-read",rule:"Your project instructions survive context resets",prompt:"Continues exactly where you left off",decision:"Applied automatically \u2014 won\u2019t ask again",task:"Picks up from where it stopped",error:"Tracked and monitored across compacts",git:"Branch, commit, and repo state preserved",env:"Runtime config carried forward",mcp:"Tool usage patterns remembered",subagent:"Delegation history preserved",skill:"Skill invocations tracked"},Ko=class{db;constructor(e){this.db=e}static contextSavingsTotal(e,r){let n=e-r,o=e>0?Math.round(n/e*1e3)/10:0;return{rawBytes:e,contextBytes:r,savedBytes:n,savedPercent:o}}static thinkInCodeComparison(e,r){let n=r>0?Math.round(e/r*10)/10:0;return{fileBytes:e,outputBytes:r,ratio:n}}static toolSavings(e){return e.map(r=>({...r,savedBytes:r.rawBytes-r.contextBytes}))}static sandboxIO(e,r){return{inputBytes:e,outputBytes:r}}queryAll(e){let n=this.db.prepare("SELECT session_id FROM session_meta ORDER BY started_at DESC LIMIT 1").get()?.session_id??"",o=Object.values(e.bytesReturned).reduce((N,Re)=>N+Re,0),s=Object.values(e.calls).reduce((N,Re)=>N+Re,0),i=e.bytesIndexed+e.bytesSandboxed,a=i+o,c=a/Math.max(o,1),u=a>0?Math.round((1-o/a)*100):0,l=new Set([...Object.keys(e.calls),...Object.keys(e.bytesReturned)]),d=Array.from(l).sort().map(N=>({tool:N,calls:e.calls[N]||0,context_kb:Math.round((e.bytesReturned[N]||0)/1024*10)/10,tokens:Math.round((e.bytesReturned[N]||0)/4)})),h=((Date.now()-e.sessionStart)/6e4).toFixed(1),p;if(e.cacheHits>0||e.cacheBytesSaved>0){let N=a+e.cacheBytesSaved,Re=N/Math.max(o,1),de=Math.max(0,24-Math.floor((Date.now()-e.sessionStart)/(3600*1e3)));p={hits:e.cacheHits,bytes_saved:e.cacheBytesSaved,ttl_hours_left:de,total_with_cache:N,total_savings_ratio:Re}}let f=this.db.prepare("SELECT COUNT(*) as cnt FROM session_events WHERE session_id = ?").get(n).cnt,g=this.db.prepare("SELECT category, COUNT(*) as cnt FROM session_events WHERE session_id = ? GROUP BY category ORDER BY cnt DESC").all(n),y=this.db.prepare("SELECT compact_count FROM session_meta WHERE session_id = ?").get(n)?.compact_count??0,x=this.db.prepare("SELECT event_count, consumed FROM session_resume WHERE session_id = ? ORDER BY created_at DESC LIMIT 1").get(n),k=x?!x.consumed:!1,T=this.db.prepare("SELECT category, type, data FROM session_events WHERE session_id = ? ORDER BY id DESC").all(n),Z=new Map;for(let N of T){Z.has(N.category)||Z.set(N.category,new Set);let Re=Z.get(N.category);if(Re.size<5){let de=N.data;N.category==="file"?de=N.data.split("/").pop()||N.data:N.category==="prompt"&&(de=de.length>50?de.slice(0,47)+"...":de),de.length>40&&(de=de.slice(0,37)+"..."),Re.add(de)}}let V=g.map(N=>({category:N.category,count:N.cnt,label:Ej[N.category]||N.category,preview:Z.get(N.category)?Array.from(Z.get(N.category)).join(", "):"",why:Tj[N.category]||"Survives context resets"}));return{savings:{processed_kb:Math.round(a/1024*10)/10,entered_kb:Math.round(o/1024*10)/10,saved_kb:Math.round(i/1024*10)/10,pct:u,savings_ratio:Math.round(c*10)/10,by_tool:d,total_calls:s,total_bytes_returned:o,kept_out:i,total_processed:a},cache:p,session:{id:n,uptime_min:h},continuity:{total_events:f,by_category:V,compact_count:y,resume_ready:k}}}}});var Uk={};je(Uk,{extractSnippet:()=>Wh,formatBatchQueryResults:()=>Fk,positionsFromHighlight:()=>Lk});import{createRequire as zk}from"node:module";import{createHash as Rj}from"node:crypto";import{existsSync as ot,unlinkSync as Xr,readdirSync as Oj,readFileSync as jk,writeFileSync as Mk,rmSync as Fh,mkdirSync as Uh,cpSync as Cj,statSync as Ok}from"node:fs";import{execSync as Yr}from"node:child_process";import{join as xe,dirname as Qr,resolve as kr}from"node:path";import{fileURLToPath as Ij}from"node:url";import{homedir as Hh,tmpdir as qh}from"node:os";import{request as Aj}from"node:https";function Nj(t){try{let e=Bn();if(!ot(e))return;let r=Oj(e).filter(n=>n.endsWith("-events.md"));for(let n of r){let o=xe(e,n);try{t.index({path:o,source:"session-events"}),Xr(o)}catch{}}}catch{}}function Bn(){if(Kc)return Kc.getSessionDir();let t=xe(Hh(),".claude","context-mode","sessions");return Uh(t,{recursive:!0}),t}function zj(){return process.env.CLAUDE_PROJECT_DIR||process.env.GEMINI_PROJECT_DIR||process.env.VSCODE_CWD||process.env.OPENCODE_PROJECT_DIR||process.env.PI_PROJECT_DIR||process.env.CONTEXT_MODE_PROJECT_DIR||process.cwd()}function Jc(){let e=zj().replace(/\\/g,"/");return Rj("sha256").update(e).digest("hex").slice(0,16)}function Zh(){let t=Jc(),e=Bn(),r=xe(Qr(e),"content");return Uh(r,{recursive:!0}),xe(r,`${t}.db`)}function Vn(){if(!cr){let t=Zh();cr=new Bc(t);try{let e=Qr(Zh());Oh(e,14),cr.cleanupStaleSources(14);let r=xe(Hh(),".context-mode","content");ot(r)&&Oh(r,0)}catch{}Rh()}return Nj(cr),cr}async function Dj(){return new Promise(t=>{let e=Aj("https://registry.npmjs.org/context-mode/latest",{headers:{Connection:"close"}},r=>{let n="";r.on("data",o=>{n+=o}),r.on("end",()=>{try{let o=JSON.parse(n);t(o.version??"unknown")}catch{t("unknown")}})});e.on("error",()=>t("unknown")),e.setTimeout(5e3,()=>{e.destroy(),t("unknown")}),e.end()})}function Lj(){let t=Kc?.name;return t==="Claude Code"?"/ctx-upgrade":t==="OpenClaw"?"npm run install:openclaw":t==="Pi"?"npm run build":"npm update -g context-mode"}function Fj(t,e){let r=t.split(".").map(Number),n=e.split(".").map(Number);for(let o=0;o<3;o++){if((r[o]??0)>(n[o]??0))return!0;if((r[o]??0)<(n[o]??0))return!1}return!1}function Zj(){return!tn||tn==="unknown"?!1:Fj(tn,en)}function Uj(){if(!Zj())return!1;let t=Date.now();if(Wc>=jj){if(t-Ck<Mj)return!1;Wc=0}return Wc===0&&(Ck=t),Wc++,!0}function H(t,e){if(Uj()&&e.content.length>0){let n=Lj();e.content[0].text=`\u26A0\uFE0F context-mode v${en} outdated \u2192 v${tn} available. Upgrade: ${n}
342
342
 
343
343
  `+e.content[0].text}let r=e.content.reduce((n,o)=>n+Buffer.byteLength(o.text),0);return ze.calls[t]=(ze.calls[t]||0)+1,ze.bytesReturned[t]=(ze.bytesReturned[t]||0)+r,e}function Gt(t){ze.bytesIndexed+=t}function Vh(t,e){try{let r=Ih(process.env.CLAUDE_PROJECT_DIR),n=Ah(t,r);if(n.decision==="deny")return H(e,{content:[{type:"text",text:`Command blocked by security policy: matches deny pattern ${n.matchedPattern}`}],isError:!0})}catch{}return null}function Dk(t,e,r){try{let n=bk(t,e);if(n.length===0)return null;let o=Ih(process.env.CLAUDE_PROJECT_DIR);for(let s of n){let i=Ah(s,o);if(i.decision==="deny")return H(r,{content:[{type:"text",text:`Command blocked by security policy: embedded shell command "${s}" matches deny pattern ${i.matchedPattern}`}],isError:!0})}}catch{}return null}function Hj(t,e){try{let r=process.env.CLAUDE_PROJECT_DIR??process.cwd(),n=vk("Read",r),o=Sk(t,n,process.platform==="win32",r);if(o.denied)return H(e,{content:[{type:"text",text:`File access blocked by security policy: path matches Read deny pattern ${o.matchedPattern}`}],isError:!0})}catch{}return null}function Lk(t){let e=[],r=0,n=0;for(;n<t.length;)if(t[n]===Vj){for(e.push(r),n++;n<t.length&&t[n]!==Wj;)r++,n++;n<t.length&&n++}else r++,n++;return e}function Wh(t,e,r=1500,n){if(t.length<=r)return t;let o=[];if(n)for(let u of Lk(n))o.push(u);if(o.length===0){let u=e.toLowerCase().split(/\s+/).filter(d=>d.length>2),l=t.toLowerCase();for(let d of u){let m=l.indexOf(d);for(;m!==-1;)o.push(m),m=l.indexOf(d,m+1)}}if(o.length===0)return t.slice(0,r)+`
344
344
  \u2026`;o.sort((u,l)=>u-l);let s=300,i=[];for(let u of o){let l=Math.max(0,u-s),d=Math.min(t.length,u+s);i.length>0&&l<=i[i.length-1][1]?i[i.length-1][1]=d:i.push([l,d])}let a=[],c=0;for(let[u,l]of i){if(c>=r)break;let d=t.slice(u,Math.min(l,u+(r-c)));a.push((u>0?"\u2026":"")+d+(l<t.length?"\u2026":"")),c+=d.length}return a.join(`
@@ -3,7 +3,7 @@
3
3
  "name": "Context Mode",
4
4
  "kind": "tool",
5
5
  "description": "OpenClaw plugin that saves 98% of your context window. Sandboxed code execution in 11 languages, FTS5 knowledge base with BM25 ranking, and intent-driven search.",
6
- "version": "1.0.91",
6
+ "version": "1.0.92",
7
7
  "sandbox": {
8
8
  "mode": "permissive",
9
9
  "filesystem_access": "full",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "context-mode",
3
- "version": "1.0.91",
3
+ "version": "1.0.92",
4
4
  "type": "module",
5
5
  "description": "MCP plugin that saves 98% of your context window. Works with Claude Code, Gemini CLI, VS Code Copilot, OpenCode, and Codex CLI. Sandboxed code execution, FTS5 knowledge base, and intent-driven search.",
6
6
  "author": "Mert Koseoğlu",