context-compress 2026.3.21 → 2026.3.22
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/dist/executor.d.ts +7 -1
- package/dist/executor.d.ts.map +1 -1
- package/dist/executor.js +48 -4
- package/dist/executor.js.map +1 -1
- package/dist/filters.d.ts +18 -0
- package/dist/filters.d.ts.map +1 -0
- package/dist/filters.js +167 -0
- package/dist/filters.js.map +1 -0
- package/dist/server.bundle.mjs +223 -8
- package/dist/server.bundle.mjs.map +4 -4
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +11 -1
- package/dist/server.js.map +1 -1
- package/dist/stats.d.ts +7 -1
- package/dist/stats.d.ts.map +1 -1
- package/dist/stats.js +65 -0
- package/dist/stats.js.map +1 -1
- package/dist/types.d.ts +12 -0
- package/dist/types.d.ts.map +1 -1
- package/docs/token-reduction-report.md +130 -83
- package/package.json +1 -1
package/dist/server.bundle.mjs
CHANGED
|
@@ -11061,7 +11061,7 @@ function debug(...args) {
|
|
|
11061
11061
|
}
|
|
11062
11062
|
|
|
11063
11063
|
// src/server.ts
|
|
11064
|
-
import { readFileSync as
|
|
11064
|
+
import { readFileSync as readFileSync3, realpathSync, statSync } from "node:fs";
|
|
11065
11065
|
import { dirname, join as join4, resolve } from "node:path";
|
|
11066
11066
|
import { fileURLToPath } from "node:url";
|
|
11067
11067
|
|
|
@@ -21217,6 +21217,129 @@ import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
|
21217
21217
|
import { tmpdir } from "node:os";
|
|
21218
21218
|
import { join as join2 } from "node:path";
|
|
21219
21219
|
|
|
21220
|
+
// src/filters.ts
|
|
21221
|
+
function applyCommandFilter(code, stdout) {
|
|
21222
|
+
const cmd = code.trim().split(/\s+/)[0];
|
|
21223
|
+
const fullCmd = code.trim();
|
|
21224
|
+
if (cmd === "git") return filterGit(fullCmd, stdout);
|
|
21225
|
+
if (cmd === "npm" || cmd === "yarn" || cmd === "pnpm" || cmd === "bun")
|
|
21226
|
+
return filterPackageManager(fullCmd, stdout);
|
|
21227
|
+
if (fullCmd.includes("test") || fullCmd.includes("jest") || fullCmd.includes("vitest") || fullCmd.includes("pytest") || fullCmd.includes("cargo test")) {
|
|
21228
|
+
return filterTestOutput(stdout);
|
|
21229
|
+
}
|
|
21230
|
+
if (cmd === "cargo" || cmd === "make" || cmd === "gradle")
|
|
21231
|
+
return filterBuildOutput(fullCmd, stdout);
|
|
21232
|
+
if (cmd === "docker" || cmd === "kubectl") return filterContainerOutput(fullCmd, stdout);
|
|
21233
|
+
if (cmd === "ls" || cmd === "find" || cmd === "tree") return filterFileList(fullCmd, stdout);
|
|
21234
|
+
return { output: stdout, filtered: false };
|
|
21235
|
+
}
|
|
21236
|
+
function filterGit(cmd, stdout) {
|
|
21237
|
+
if (/git\s+(push|pull|fetch|clone)/.test(cmd)) {
|
|
21238
|
+
const lines = stdout.split("\n");
|
|
21239
|
+
const filtered = lines.filter(
|
|
21240
|
+
(l) => !l.startsWith("remote: Counting") && !l.startsWith("remote: Compressing") && !l.startsWith("remote: Total") && !l.includes("Unpacking objects:") && !l.includes("Receiving objects:") && !l.includes("Resolving deltas:") && !/^\s*\d+%/.test(l)
|
|
21241
|
+
);
|
|
21242
|
+
return { output: filtered.join("\n"), filtered: true };
|
|
21243
|
+
}
|
|
21244
|
+
if (/git\s+status/.test(cmd)) {
|
|
21245
|
+
const lines = stdout.split("\n");
|
|
21246
|
+
const filtered = lines.filter((l) => !l.startsWith(" (use ") && l.trim() !== "");
|
|
21247
|
+
return { output: filtered.join("\n"), filtered: true };
|
|
21248
|
+
}
|
|
21249
|
+
return { output: stdout, filtered: false };
|
|
21250
|
+
}
|
|
21251
|
+
function filterPackageManager(cmd, stdout) {
|
|
21252
|
+
if (/\b(install|add|i)\b/.test(cmd)) {
|
|
21253
|
+
const lines = stdout.split("\n");
|
|
21254
|
+
const filtered = lines.filter(
|
|
21255
|
+
(l) => !l.startsWith("npm warn") && !l.includes("packages are looking for funding") && !l.includes("run `npm fund`") && !l.startsWith("npm notice") && !/^[\s\u2502\u251C\u2514\u2500]+$/.test(l) && // tree-drawing characters
|
|
21256
|
+
!/^\s*$/.test(l)
|
|
21257
|
+
);
|
|
21258
|
+
return { output: filtered.join("\n"), filtered: true };
|
|
21259
|
+
}
|
|
21260
|
+
if (/\btest\b/.test(cmd)) {
|
|
21261
|
+
return filterTestOutput(stdout);
|
|
21262
|
+
}
|
|
21263
|
+
return { output: stdout, filtered: false };
|
|
21264
|
+
}
|
|
21265
|
+
var FAIL_MARKER_RE = /^\s*[\u2717\u2718\u00D7]\s/;
|
|
21266
|
+
var FAIL_WORD_RE = /\bFAIL\b/;
|
|
21267
|
+
var FAILED_RE = /\bfailed?\b/i;
|
|
21268
|
+
var ERROR_RE = /\bERROR\b/;
|
|
21269
|
+
var SUMMARY_RE = /^\s*(Tests?|Suites?|Test Suites)\s*:|^\s*(pass|fail|skip|pending|todo)\s|\b\d+\s+(passing|failing|pending|skipped)\b|^(ok|not ok)\s|^\u2139\s|^(PASS|FAIL)\s/i;
|
|
21270
|
+
function isFailMarker(line) {
|
|
21271
|
+
return FAIL_MARKER_RE.test(line) || FAIL_WORD_RE.test(line) || FAILED_RE.test(line) || ERROR_RE.test(line);
|
|
21272
|
+
}
|
|
21273
|
+
function isSummaryLine(line) {
|
|
21274
|
+
return SUMMARY_RE.test(line);
|
|
21275
|
+
}
|
|
21276
|
+
function filterTestOutput(stdout) {
|
|
21277
|
+
const lines = stdout.split("\n");
|
|
21278
|
+
const failures = [];
|
|
21279
|
+
const summary = [];
|
|
21280
|
+
let inFailure = false;
|
|
21281
|
+
let failCount = 0;
|
|
21282
|
+
for (const line of lines) {
|
|
21283
|
+
if (isFailMarker(line)) {
|
|
21284
|
+
inFailure = true;
|
|
21285
|
+
failCount++;
|
|
21286
|
+
}
|
|
21287
|
+
if (inFailure) {
|
|
21288
|
+
failures.push(line);
|
|
21289
|
+
if (line.trim() === "" && failures.length > 3) inFailure = false;
|
|
21290
|
+
}
|
|
21291
|
+
if (isSummaryLine(line)) {
|
|
21292
|
+
summary.push(line);
|
|
21293
|
+
}
|
|
21294
|
+
}
|
|
21295
|
+
if (failCount === 0 && summary.length > 0) {
|
|
21296
|
+
return { output: summary.join("\n"), filtered: true };
|
|
21297
|
+
}
|
|
21298
|
+
if (failures.length > 0) {
|
|
21299
|
+
const result = [...failures, "", ...summary].join("\n");
|
|
21300
|
+
return { output: result, filtered: true };
|
|
21301
|
+
}
|
|
21302
|
+
return { output: stdout, filtered: false };
|
|
21303
|
+
}
|
|
21304
|
+
function filterBuildOutput(cmd, stdout) {
|
|
21305
|
+
const lines = stdout.split("\n");
|
|
21306
|
+
const filtered = lines.filter(
|
|
21307
|
+
(l) => !l.includes("Downloading") && !l.includes("Downloaded") && !/Compiling\s+\d+\s+of\s+\d+/.test(l) && !l.includes("Blocking waiting for file lock") && !/^\s*$/.test(l)
|
|
21308
|
+
);
|
|
21309
|
+
return { output: filtered.join("\n"), filtered: filtered.length < lines.length };
|
|
21310
|
+
}
|
|
21311
|
+
function filterContainerOutput(cmd, stdout) {
|
|
21312
|
+
if (/docker\s+build/.test(cmd)) {
|
|
21313
|
+
const lines = stdout.split("\n");
|
|
21314
|
+
const filtered = lines.filter(
|
|
21315
|
+
(l) => !l.startsWith(" ---> ") && !l.startsWith("Sending build context")
|
|
21316
|
+
);
|
|
21317
|
+
return { output: filtered.join("\n"), filtered: true };
|
|
21318
|
+
}
|
|
21319
|
+
return { output: stdout, filtered: false };
|
|
21320
|
+
}
|
|
21321
|
+
function filterFileList(cmd, stdout) {
|
|
21322
|
+
const lines = stdout.split("\n").filter((l) => l.trim() !== "");
|
|
21323
|
+
if (lines.length <= 30) return { output: stdout, filtered: false };
|
|
21324
|
+
if (cmd.includes("-R") || cmd.startsWith("find")) {
|
|
21325
|
+
const dirs = /* @__PURE__ */ new Map();
|
|
21326
|
+
for (const line of lines) {
|
|
21327
|
+
const parts = line.split("/");
|
|
21328
|
+
const dir = parts.length > 1 ? parts.slice(0, -1).join("/") : ".";
|
|
21329
|
+
dirs.set(dir, (dirs.get(dir) ?? 0) + 1);
|
|
21330
|
+
}
|
|
21331
|
+
if (dirs.size > 5 && lines.length > 50) {
|
|
21332
|
+
const summary = Array.from(dirs.entries()).sort((a, b) => b[1] - a[1]).map(([dir, count]) => ` ${dir}/ (${count} files)`).join("\n");
|
|
21333
|
+
return {
|
|
21334
|
+
output: `${lines.length} files found:
|
|
21335
|
+
${summary}`,
|
|
21336
|
+
filtered: true
|
|
21337
|
+
};
|
|
21338
|
+
}
|
|
21339
|
+
}
|
|
21340
|
+
return { output: stdout, filtered: false };
|
|
21341
|
+
}
|
|
21342
|
+
|
|
21220
21343
|
// src/utils.ts
|
|
21221
21344
|
function detectInjectionPatterns(content) {
|
|
21222
21345
|
const warnings = [];
|
|
@@ -21265,6 +21388,10 @@ function formatBytes(bytes) {
|
|
|
21265
21388
|
|
|
21266
21389
|
// src/executor.ts
|
|
21267
21390
|
var DEFAULT_TIMEOUT = 3e4;
|
|
21391
|
+
var ANSI_RE = /\x1b\[[0-9;]*[a-zA-Z]/;
|
|
21392
|
+
function stripAnsi(str) {
|
|
21393
|
+
return str.replace(new RegExp(ANSI_RE.source, "g"), "");
|
|
21394
|
+
}
|
|
21268
21395
|
var SAFE_ENV_KEYS = [
|
|
21269
21396
|
"PATH",
|
|
21270
21397
|
"HOME",
|
|
@@ -21317,6 +21444,21 @@ function killProcessTree(pid) {
|
|
|
21317
21444
|
}
|
|
21318
21445
|
}
|
|
21319
21446
|
}
|
|
21447
|
+
function stripProgressLines(output) {
|
|
21448
|
+
const lines = output.split("\n");
|
|
21449
|
+
const filtered = lines.filter((l) => {
|
|
21450
|
+
const trimmed = l.trim();
|
|
21451
|
+
if (ANSI_RE.test(l) && trimmed.replace(new RegExp(ANSI_RE.source, "g"), "").trim() === "")
|
|
21452
|
+
return false;
|
|
21453
|
+
if (/^[\s\[│├└─═━▓░█▒▏▎▍▌▋▊▉\]>=#\-.\d%]+$/.test(trimmed) && trimmed.length > 3) return false;
|
|
21454
|
+
if (/^[⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏\-\\|/]\s/.test(trimmed)) return false;
|
|
21455
|
+
if (/(?:downloading|uploading|fetching|resolving)\s+[\d.]+\s*[kmg]?b/i.test(trimmed))
|
|
21456
|
+
return false;
|
|
21457
|
+
if (/\d+\.?\d*\s*[kmg]?b\/s/i.test(trimmed) && /eta|remaining/i.test(trimmed)) return false;
|
|
21458
|
+
return true;
|
|
21459
|
+
});
|
|
21460
|
+
return filtered.join("\n");
|
|
21461
|
+
}
|
|
21320
21462
|
function deduplicateLines(output) {
|
|
21321
21463
|
const lines = output.split("\n");
|
|
21322
21464
|
if (lines.length < 3) return output;
|
|
@@ -21348,12 +21490,12 @@ function deduplicateLines(output) {
|
|
|
21348
21490
|
function groupErrorLines(output) {
|
|
21349
21491
|
const lines = output.split("\n");
|
|
21350
21492
|
if (lines.length < 5) return output;
|
|
21351
|
-
const
|
|
21493
|
+
const ERROR_RE2 = /^(.*?(?:error|warning|Error|Warning|ERR|WARN)[:\s])\s*(.+?)(?:\s+(?:at|in|on)\s+(?:line\s+)?(\d+))?$/i;
|
|
21352
21494
|
const errorGroups = /* @__PURE__ */ new Map();
|
|
21353
21495
|
const resultLines = [];
|
|
21354
21496
|
let groupedCount = 0;
|
|
21355
21497
|
for (const line of lines) {
|
|
21356
|
-
const match = line.match(
|
|
21498
|
+
const match = line.match(ERROR_RE2);
|
|
21357
21499
|
if (match) {
|
|
21358
21500
|
const prefix = match[1].trim();
|
|
21359
21501
|
const msg = match[2].trim();
|
|
@@ -21505,7 +21647,8 @@ var SubprocessExecutor = class {
|
|
|
21505
21647
|
tmpDir,
|
|
21506
21648
|
timeout,
|
|
21507
21649
|
maxOutput,
|
|
21508
|
-
plugin.needsShell
|
|
21650
|
+
plugin.needsShell,
|
|
21651
|
+
opts.language === "shell" ? opts.code : void 0
|
|
21509
21652
|
);
|
|
21510
21653
|
} finally {
|
|
21511
21654
|
setTimeout(() => this.cleanupTempDir(tmpDir), 100).unref();
|
|
@@ -21532,7 +21675,7 @@ var SubprocessExecutor = class {
|
|
|
21532
21675
|
}
|
|
21533
21676
|
return this.execute({ ...opts, code });
|
|
21534
21677
|
}
|
|
21535
|
-
spawnAndCapture(cmd, args, cwd, timeout, maxOutput, useShell) {
|
|
21678
|
+
spawnAndCapture(cmd, args, cwd, timeout, maxOutput, useShell, shellCode) {
|
|
21536
21679
|
return new Promise((resolve2) => {
|
|
21537
21680
|
const hardCap = this.config.hardCapBytes;
|
|
21538
21681
|
const stdoutChunks = [];
|
|
@@ -21597,7 +21740,15 @@ var SubprocessExecutor = class {
|
|
|
21597
21740
|
stdout += `
|
|
21598
21741
|
[output capped at ${formatBytes(hardCap)} \u2014 process killed]`;
|
|
21599
21742
|
}
|
|
21743
|
+
if (shellCode && stdout) {
|
|
21744
|
+
const filtered = applyCommandFilter(shellCode, stdout);
|
|
21745
|
+
if (filtered.filtered) {
|
|
21746
|
+
stdout = filtered.output;
|
|
21747
|
+
}
|
|
21748
|
+
}
|
|
21749
|
+
stdout = stripAnsi(stdout);
|
|
21600
21750
|
if (stdout.length > 1e4) {
|
|
21751
|
+
stdout = stripProgressLines(stdout);
|
|
21601
21752
|
stdout = deduplicateLines(stdout);
|
|
21602
21753
|
stdout = groupErrorLines(stdout);
|
|
21603
21754
|
}
|
|
@@ -22013,6 +22164,7 @@ function hasBun(runtimes) {
|
|
|
22013
22164
|
}
|
|
22014
22165
|
|
|
22015
22166
|
// src/stats.ts
|
|
22167
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
22016
22168
|
var BAR_WIDTH = 20;
|
|
22017
22169
|
function asciiBar(ratio, width = BAR_WIDTH) {
|
|
22018
22170
|
const filled = Math.round(ratio * width);
|
|
@@ -22032,6 +22184,10 @@ var SessionTracker = class {
|
|
|
22032
22184
|
bytesSandboxed: 0,
|
|
22033
22185
|
sessionStart: Date.now()
|
|
22034
22186
|
};
|
|
22187
|
+
cumulativeFile;
|
|
22188
|
+
constructor(cumulativeFile) {
|
|
22189
|
+
this.cumulativeFile = cumulativeFile ?? null;
|
|
22190
|
+
}
|
|
22035
22191
|
trackCall(toolName, responseBytes) {
|
|
22036
22192
|
this.stats.calls[toolName] = (this.stats.calls[toolName] ?? 0) + 1;
|
|
22037
22193
|
this.stats.bytesReturned[toolName] = (this.stats.bytesReturned[toolName] ?? 0) + responseBytes;
|
|
@@ -22045,6 +22201,47 @@ var SessionTracker = class {
|
|
|
22045
22201
|
getSnapshot() {
|
|
22046
22202
|
return { ...this.stats };
|
|
22047
22203
|
}
|
|
22204
|
+
/** Load cumulative stats from disk */
|
|
22205
|
+
loadCumulative() {
|
|
22206
|
+
if (!this.cumulativeFile) return null;
|
|
22207
|
+
try {
|
|
22208
|
+
const data = readFileSync2(this.cumulativeFile, "utf-8");
|
|
22209
|
+
return JSON.parse(data);
|
|
22210
|
+
} catch {
|
|
22211
|
+
return null;
|
|
22212
|
+
}
|
|
22213
|
+
}
|
|
22214
|
+
/** Save current session stats to cumulative file */
|
|
22215
|
+
saveCumulative() {
|
|
22216
|
+
if (!this.cumulativeFile) return;
|
|
22217
|
+
const snap = this.stats;
|
|
22218
|
+
const keptOut = snap.bytesIndexed + snap.bytesSandboxed;
|
|
22219
|
+
const totalReturned = Object.values(snap.bytesReturned).reduce((a, b) => a + b, 0);
|
|
22220
|
+
const cumulative = this.loadCumulative() ?? {
|
|
22221
|
+
totalBytesSaved: 0,
|
|
22222
|
+
totalBytesProcessed: 0,
|
|
22223
|
+
totalCalls: 0,
|
|
22224
|
+
totalSessions: 0,
|
|
22225
|
+
firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22226
|
+
lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22227
|
+
perCommand: {}
|
|
22228
|
+
};
|
|
22229
|
+
cumulative.totalBytesSaved += keptOut;
|
|
22230
|
+
cumulative.totalBytesProcessed += keptOut + totalReturned;
|
|
22231
|
+
cumulative.totalCalls += Object.values(snap.calls).reduce((a, b) => a + b, 0);
|
|
22232
|
+
cumulative.totalSessions += 1;
|
|
22233
|
+
cumulative.lastSeen = (/* @__PURE__ */ new Date()).toISOString();
|
|
22234
|
+
for (const [name, calls] of Object.entries(snap.calls)) {
|
|
22235
|
+
if (!cumulative.perCommand[name]) {
|
|
22236
|
+
cumulative.perCommand[name] = { calls: 0, bytesSaved: 0 };
|
|
22237
|
+
}
|
|
22238
|
+
cumulative.perCommand[name].calls += calls;
|
|
22239
|
+
}
|
|
22240
|
+
try {
|
|
22241
|
+
writeFileSync2(this.cumulativeFile, JSON.stringify(cumulative, null, 2));
|
|
22242
|
+
} catch {
|
|
22243
|
+
}
|
|
22244
|
+
}
|
|
22048
22245
|
formatReport() {
|
|
22049
22246
|
const snap = this.stats;
|
|
22050
22247
|
const elapsed = Date.now() - snap.sessionStart;
|
|
@@ -22105,6 +22302,18 @@ var SessionTracker = class {
|
|
|
22105
22302
|
`
|
|
22106
22303
|
Context-compress kept ${formatBytes(keptOut)} out of context (${reductionPct}% savings).`
|
|
22107
22304
|
);
|
|
22305
|
+
const cumulative = this.loadCumulative();
|
|
22306
|
+
if (cumulative) {
|
|
22307
|
+
lines.push("\n## Cumulative Savings (All Sessions)\n");
|
|
22308
|
+
lines.push("| Metric | Value |");
|
|
22309
|
+
lines.push("|--------|-------|");
|
|
22310
|
+
lines.push(`| Sessions tracked | ${cumulative.totalSessions} |`);
|
|
22311
|
+
lines.push(`| Total data processed | ${formatBytes(cumulative.totalBytesProcessed)} |`);
|
|
22312
|
+
lines.push(`| Total kept out of context | ${formatBytes(cumulative.totalBytesSaved)} |`);
|
|
22313
|
+
const cumTokensMid = Math.round(cumulative.totalBytesSaved / 4);
|
|
22314
|
+
lines.push(`| Est. total tokens saved | ~${cumTokensMid.toLocaleString()} |`);
|
|
22315
|
+
lines.push(`| Tracking since | ${cumulative.firstSeen.split("T")[0]} |`);
|
|
22316
|
+
}
|
|
22108
22317
|
return lines.join("\n");
|
|
22109
22318
|
}
|
|
22110
22319
|
};
|
|
@@ -22722,7 +22931,7 @@ function getVersion() {
|
|
|
22722
22931
|
try {
|
|
22723
22932
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
22724
22933
|
const pkgPath = join4(__dirname, "..", "package.json");
|
|
22725
|
-
const pkg = JSON.parse(
|
|
22934
|
+
const pkg = JSON.parse(readFileSync3(pkgPath, "utf-8"));
|
|
22726
22935
|
return pkg.version ?? "1.0.0";
|
|
22727
22936
|
} catch {
|
|
22728
22937
|
return "1.0.0";
|
|
@@ -22757,7 +22966,8 @@ async function createServer(config3) {
|
|
|
22757
22966
|
store = new ContentStore(":memory:");
|
|
22758
22967
|
dbFallback = true;
|
|
22759
22968
|
}
|
|
22760
|
-
const
|
|
22969
|
+
const cumulativeFile = config3.persistDb ? join4(config3.dbDir ?? join4(projectDir, ".context-compress"), "stats.json") : void 0;
|
|
22970
|
+
const tracker = new SessionTracker(cumulativeFile);
|
|
22761
22971
|
let activeExecutions = 0;
|
|
22762
22972
|
const MAX_CONCURRENT_EXECUTIONS = 8;
|
|
22763
22973
|
const EXECUTION_LIMIT_ERROR = "Error: too many concurrent executions. Try again shortly.";
|
|
@@ -22796,6 +23006,10 @@ Searchable terms: ${terms.join(", ")}
|
|
|
22796
23006
|
return compactLabel(filtered, config3.compressionLevel);
|
|
22797
23007
|
}
|
|
22798
23008
|
const shutdown = () => {
|
|
23009
|
+
try {
|
|
23010
|
+
tracker.saveCumulative();
|
|
23011
|
+
} catch {
|
|
23012
|
+
}
|
|
22799
23013
|
try {
|
|
22800
23014
|
executor.shutdown();
|
|
22801
23015
|
} catch {
|
|
@@ -22974,7 +23188,7 @@ ${result.stderr}`;
|
|
|
22974
23188
|
]
|
|
22975
23189
|
};
|
|
22976
23190
|
}
|
|
22977
|
-
text =
|
|
23191
|
+
text = readFileSync3(absPath, "utf-8");
|
|
22978
23192
|
label = source ?? filePath;
|
|
22979
23193
|
} catch (e) {
|
|
22980
23194
|
const msg = e instanceof Error ? e.message : String(e);
|
|
@@ -23255,6 +23469,7 @@ Searchable terms: ${terms.join(", ")}`;
|
|
|
23255
23469
|
"Returns context consumption statistics for the current session. Shows total bytes returned to context, breakdown by tool, call counts, estimated token usage, context savings ratio, and visual charts.",
|
|
23256
23470
|
{},
|
|
23257
23471
|
async () => {
|
|
23472
|
+
tracker.saveCumulative();
|
|
23258
23473
|
const report = tracker.formatReport();
|
|
23259
23474
|
tracker.trackCall("stats", Buffer.byteLength(report));
|
|
23260
23475
|
return { content: [{ type: "text", text: report }] };
|