pi-lens
Version:
Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo
107 lines (105 loc) • 3.12 kB
JavaScript
import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
import {
createSubsystemLogger
} from "./chunk-O6TQT6RI.js";
import "./chunk-UK3CMEAL.js";
import "./chunk-Q5U6FMDI.js";
import "./chunk-NXL4FFQQ.js";
// dist/clients/metrics-client.js
import * as fs from "node:fs";
import * as path from "node:path";
var MetricsClient = class {
log;
fileBaselines = /* @__PURE__ */ new Map();
constructor(verbose = false) {
this.log = verbose ? createSubsystemLogger("metrics") : () => {
};
}
/**
* Record initial state of a file when first touched this session
*/
recordBaseline(filePath) {
const absolutePath = path.resolve(filePath);
if (!fs.existsSync(absolutePath))
return;
if (this.fileBaselines.has(absolutePath))
return;
const content = fs.readFileSync(absolutePath, "utf-8");
const entropy = this.calculateEntropy(content);
this.fileBaselines.set(absolutePath, { content, entropy });
this.log(`Baseline recorded: ${path.basename(filePath)} (entropy: ${entropy.toFixed(2)})`);
}
/**
* Get metrics for a specific file
*/
getFileMetrics(filePath) {
const absolutePath = path.resolve(filePath);
const baseline = this.fileBaselines.get(absolutePath);
if (!baseline)
return null;
if (!fs.existsSync(absolutePath))
return null;
const currentContent = fs.readFileSync(absolutePath, "utf-8");
const totalLines = currentContent.split("\n").length;
const entropyCurrent = this.calculateEntropy(currentContent);
const entropyDelta = entropyCurrent - baseline.entropy;
return {
filePath: path.relative(process.cwd(), absolutePath),
totalLines,
entropyStart: baseline.entropy,
entropyCurrent,
entropyDelta
};
}
/**
* Get entropy delta for all touched files
*/
getEntropyDeltas() {
const results = [];
for (const [filePath, baseline] of this.fileBaselines) {
if (!fs.existsSync(filePath))
continue;
const content = fs.readFileSync(filePath, "utf-8");
const current = this.calculateEntropy(content);
const delta = current - baseline.entropy;
results.push({
file: path.relative(process.cwd(), filePath),
start: baseline.entropy,
current,
delta
});
}
return results.sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));
}
/**
* Calculate Shannon entropy of a string
* Returns bits per character
*/
calculateEntropy(text) {
if (text.length === 0)
return 0;
const freq = /* @__PURE__ */ new Map();
for (const char of text) {
freq.set(char, (freq.get(char) || 0) + 1);
}
let entropy = 0;
const len = text.length;
for (const count of freq.values()) {
const p = count / len;
if (p > 0) {
entropy -= p * Math.log2(p);
}
}
return entropy;
}
/**
* Reset session state (for new session)
*/
reset() {
this.fileBaselines.clear();
this.log("Session metrics reset");
}
};
export {
MetricsClient
};