context-mode 1.0.70 → 1.0.71
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/.openclaw-plugin/openclaw.plugin.json +1 -1
- package/.openclaw-plugin/package.json +1 -1
- package/build/server.js +19 -0
- package/build/session/analytics.d.ts +3 -3
- package/build/session/analytics.js +76 -43
- package/cli.bundle.mjs +108 -94
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
- package/server.bundle.mjs +82 -68
|
@@ -6,14 +6,14 @@
|
|
|
6
6
|
},
|
|
7
7
|
"metadata": {
|
|
8
8
|
"description": "Claude Code plugins by Mert Koseoğlu",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.71"
|
|
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.
|
|
16
|
+
"version": "1.0.71",
|
|
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.
|
|
3
|
+
"version": "1.0.71",
|
|
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.
|
|
6
|
+
"version": "1.0.71",
|
|
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.
|
|
3
|
+
"version": "1.0.71",
|
|
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",
|
package/build/server.js
CHANGED
|
@@ -531,6 +531,19 @@ server.registerTool("ctx_execute", {
|
|
|
531
531
|
// The closure approach (function(__cm_req){ var require=...; })(require) correctly
|
|
532
532
|
// shadows the CJS require for all code inside, including __cm_main().
|
|
533
533
|
instrumentedCode = `
|
|
534
|
+
// FS read instrumentation — count bytes read via fs.readFileSync/readFile
|
|
535
|
+
let __cm_fs=0;
|
|
536
|
+
process.on('exit',()=>{if(__cm_fs>0)try{process.stderr.write('__CM_FS__:'+__cm_fs+'\\n')}catch{}});
|
|
537
|
+
(function(){
|
|
538
|
+
try{
|
|
539
|
+
var f=typeof require!=='undefined'?require('fs'):null;
|
|
540
|
+
if(!f)return;
|
|
541
|
+
var ors=f.readFileSync;
|
|
542
|
+
f.readFileSync=function(){var r=ors.apply(this,arguments);if(Buffer.isBuffer(r))__cm_fs+=r.length;else if(typeof r==='string')__cm_fs+=Buffer.byteLength(r);return r;};
|
|
543
|
+
var orf=f.readFile;
|
|
544
|
+
if(orf)f.readFile=function(){var a=Array.from(arguments),cb=a.pop();orf.apply(this,a.concat([function(e,d){if(!e&&d){if(Buffer.isBuffer(d))__cm_fs+=d.length;else if(typeof d==='string')__cm_fs+=Buffer.byteLength(d);}cb(e,d);}]));};
|
|
545
|
+
}catch{}
|
|
546
|
+
})();
|
|
534
547
|
let __cm_net=0;
|
|
535
548
|
// Report network bytes on process exit — works with both promise and callback patterns.
|
|
536
549
|
// process.on('exit') fires after all I/O completes, unlike .finally() which fires
|
|
@@ -585,6 +598,12 @@ __cm_main().catch(e=>{console.error(e);process.exitCode=1});${background ? '\nse
|
|
|
585
598
|
// Clean the metric line from stderr
|
|
586
599
|
result.stderr = result.stderr.replace(/\n?__CM_NET__:\d+\n?/g, "");
|
|
587
600
|
}
|
|
601
|
+
// Parse sandbox FS read metrics from stderr
|
|
602
|
+
const fsMatch = result.stderr?.match(/__CM_FS__:(\d+)/);
|
|
603
|
+
if (fsMatch) {
|
|
604
|
+
sessionStats.bytesSandboxed += parseInt(fsMatch[1]);
|
|
605
|
+
result.stderr = result.stderr.replace(/\n?__CM_FS__:\d+\n?/g, "");
|
|
606
|
+
}
|
|
588
607
|
if (result.timedOut) {
|
|
589
608
|
const partialOutput = result.stdout?.trim();
|
|
590
609
|
if (result.backgrounded && partialOutput) {
|
|
@@ -373,9 +373,9 @@ export declare class AnalyticsEngine {
|
|
|
373
373
|
queryAll(runtimeStats: RuntimeStats): FullReport;
|
|
374
374
|
}
|
|
375
375
|
/**
|
|
376
|
-
* Render a FullReport as
|
|
376
|
+
* Render a FullReport as a marketing-friendly, outcome-focused session story.
|
|
377
377
|
*
|
|
378
|
-
*
|
|
379
|
-
*
|
|
378
|
+
* Framework: Persona -> Metric -> Evidence -> Action -> ROI
|
|
379
|
+
* The output tells a narrative instead of dumping raw numbers.
|
|
380
380
|
*/
|
|
381
381
|
export declare function formatReport(report: FullReport): string;
|
|
@@ -613,62 +613,95 @@ function kb(b) {
|
|
|
613
613
|
return `${(b / 1024).toFixed(1)}KB`;
|
|
614
614
|
}
|
|
615
615
|
/**
|
|
616
|
-
* Render a FullReport as
|
|
616
|
+
* Render a FullReport as a marketing-friendly, outcome-focused session story.
|
|
617
617
|
*
|
|
618
|
-
*
|
|
619
|
-
*
|
|
618
|
+
* Framework: Persona -> Metric -> Evidence -> Action -> ROI
|
|
619
|
+
* The output tells a narrative instead of dumping raw numbers.
|
|
620
620
|
*/
|
|
621
621
|
export function formatReport(report) {
|
|
622
|
-
const lines = [
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
// ── Feature 1: Context Window Protection ──
|
|
626
|
-
lines.push("", `### Context Window Protection`, "");
|
|
622
|
+
const lines = [];
|
|
623
|
+
// ── Hero: headline story ──
|
|
624
|
+
lines.push(`## Think in Code -- Session Report`);
|
|
627
625
|
if (report.savings.total_calls === 0) {
|
|
628
|
-
lines.push(
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
626
|
+
lines.push("", "No sandbox activity yet. Use ctx_execute or ctx_batch_execute to start saving context.", "", "---", "_Display this entire report as-is in your response. Do NOT summarize, collapse, or paraphrase any section._");
|
|
627
|
+
return lines.join("\n");
|
|
628
|
+
}
|
|
629
|
+
const totalProcessed = report.savings.kept_out + (report.cache ? report.cache.bytes_saved : 0);
|
|
630
|
+
const totalReturned = report.savings.total_bytes_returned;
|
|
631
|
+
const grandTotal = totalProcessed + totalReturned;
|
|
632
|
+
const savingsPercent = grandTotal > 0
|
|
633
|
+
? ((1 - totalReturned / grandTotal) * 100).toFixed(1)
|
|
634
|
+
: "0.0";
|
|
635
|
+
// Rough estimate: 4 bytes per token, ~2 min reading time per 1000 tokens
|
|
636
|
+
const tokensSaved = Math.round(totalProcessed / 4);
|
|
637
|
+
const extraMinutes = Math.round((tokensSaved / 1000) * 2);
|
|
638
|
+
lines.push("", `Your agent processed ${kb(totalProcessed)} of data.`, `Only ${kb(totalReturned)} entered your context window.`, "", `**Context saved: ${savingsPercent}% -- session extended by ~${extraMinutes} minutes**`);
|
|
639
|
+
// ── What happened ──
|
|
640
|
+
lines.push("", "### What happened", "");
|
|
641
|
+
// Count per-tool categories
|
|
642
|
+
const toolCallMap = new Map();
|
|
643
|
+
for (const t of report.savings.by_tool) {
|
|
644
|
+
toolCallMap.set(t.tool, t.calls);
|
|
645
|
+
}
|
|
646
|
+
const executeCount = (toolCallMap.get("ctx_execute") ?? 0) +
|
|
647
|
+
(toolCallMap.get("ctx_execute_file") ?? 0);
|
|
648
|
+
const batchCount = toolCallMap.get("ctx_batch_execute") ?? 0;
|
|
649
|
+
const searchCount = toolCallMap.get("ctx_search") ?? 0;
|
|
650
|
+
const fetchCount = toolCallMap.get("ctx_fetch_and_index") ?? 0;
|
|
651
|
+
const fileCount = executeCount + batchCount;
|
|
652
|
+
const networkCount = fetchCount;
|
|
653
|
+
const cacheCount = report.cache ? report.cache.hits : 0;
|
|
654
|
+
if (fileCount > 0) {
|
|
655
|
+
lines.push(`-> ${fileCount} file${fileCount !== 1 ? "s" : ""} analyzed in sandbox (never entered context)`);
|
|
656
|
+
}
|
|
657
|
+
if (networkCount > 0) {
|
|
658
|
+
lines.push(`-> ${networkCount} API call${networkCount !== 1 ? "s" : ""} sandboxed (responses indexed, not dumped)`);
|
|
659
|
+
}
|
|
660
|
+
if (searchCount > 0) {
|
|
661
|
+
lines.push(`-> ${searchCount} search quer${searchCount !== 1 ? "ies" : "y"} served from index`);
|
|
662
|
+
}
|
|
663
|
+
if (cacheCount > 0) {
|
|
664
|
+
lines.push(`-> ${cacheCount} repeat fetch${cacheCount !== 1 ? "es" : ""} avoided (TTL cache)`);
|
|
665
|
+
}
|
|
666
|
+
// ── Per-tool breakdown ──
|
|
667
|
+
const activatedTools = report.savings.by_tool.filter((t) => t.calls > 0);
|
|
668
|
+
if (activatedTools.length > 0) {
|
|
669
|
+
lines.push("", "### Per-tool breakdown", "", "| Tool | Calls | Data processed | Context used | Saved |", "|------|------:|---------------:|-------------:|------:|");
|
|
670
|
+
for (const t of activatedTools) {
|
|
671
|
+
const processed = t.tokens * 4; // bytes approximation from tokens
|
|
672
|
+
const contextUsed = t.context_kb * 1024;
|
|
673
|
+
const savedPct = processed > 0
|
|
674
|
+
? (((processed - contextUsed) / processed) *
|
|
675
|
+
100).toFixed(0)
|
|
676
|
+
: "--";
|
|
677
|
+
lines.push(`| ${t.tool} | ${t.calls} | ${kb(processed)} | ${kb(contextUsed)} | ${savedPct}% |`);
|
|
649
678
|
}
|
|
650
679
|
}
|
|
651
|
-
// ── Session
|
|
680
|
+
// ── Session continuity ──
|
|
652
681
|
if (report.continuity.total_events > 0) {
|
|
653
|
-
lines.push("", "### Session
|
|
654
|
-
|
|
655
|
-
|
|
682
|
+
lines.push("", "### Session continuity", "");
|
|
683
|
+
const parts = [];
|
|
684
|
+
if (report.continuity.compact_count > 0) {
|
|
685
|
+
parts.push(`${report.continuity.compact_count} compaction${report.continuity.compact_count !== 1 ? "s" : ""}`);
|
|
686
|
+
}
|
|
687
|
+
parts.push(`${report.continuity.total_events} event${report.continuity.total_events !== 1 ? "s" : ""} preserved`);
|
|
688
|
+
// Count tasks from continuity categories
|
|
689
|
+
const taskRow = report.continuity.by_category.find((c) => c.category === "task" || c.category === "tasks");
|
|
690
|
+
if (taskRow && taskRow.count > 0) {
|
|
691
|
+
parts.push(`${taskRow.count} task${taskRow.count !== 1 ? "s" : ""} tracked`);
|
|
656
692
|
}
|
|
657
|
-
lines.push(
|
|
658
|
-
lines.push("");
|
|
693
|
+
lines.push(parts.join(" | "));
|
|
659
694
|
if (report.continuity.compact_count > 0) {
|
|
660
|
-
lines.push(`
|
|
695
|
+
lines.push("", `Session knowledge preserved across ${report.continuity.compact_count} compaction${report.continuity.compact_count !== 1 ? "s" : ""} -- zero context lost.`);
|
|
661
696
|
}
|
|
662
697
|
else {
|
|
663
|
-
lines.push(
|
|
698
|
+
lines.push("", "When your context compacts, all of this will restore awareness -- no starting from scratch.");
|
|
664
699
|
}
|
|
665
700
|
if (report.continuity.resume_ready) {
|
|
666
|
-
lines.push(
|
|
701
|
+
lines.push("Resume snapshot ready for the next compaction.");
|
|
667
702
|
}
|
|
668
|
-
lines.push("");
|
|
669
|
-
lines.push(`> **Note:** Previous session data is loaded when you start a new session. Without \`--continue\`, old session history is cleaned up to keep the database lean.`);
|
|
670
703
|
}
|
|
671
|
-
// ── Analytics JSON ──
|
|
704
|
+
// ── Analytics JSON (for power users) ──
|
|
672
705
|
const analyticsJson = {
|
|
673
706
|
session: {
|
|
674
707
|
duration_min: report.session.duration_min,
|
|
@@ -702,7 +735,7 @@ export function formatReport(report) {
|
|
|
702
735
|
continuity: { total_events: report.continuity.total_events },
|
|
703
736
|
};
|
|
704
737
|
lines.push("", "### Analytics (27 metrics)", "", "```json", JSON.stringify(analyticsJson, null, 2), "```");
|
|
705
|
-
//
|
|
706
|
-
lines.push("", "---", "_Display this entire report as-is in your response. Do NOT summarize, collapse, or paraphrase any section._");
|
|
738
|
+
// Footer
|
|
739
|
+
lines.push("", "---", "context-mode -- github.com/mksglu/context-mode", "", "_Display this entire report as-is in your response. Do NOT summarize, collapse, or paraphrase any section._");
|
|
707
740
|
return lines.join("\n");
|
|
708
741
|
}
|