pi-lens
Version:
Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo
479 lines (471 loc) • 15.9 kB
JavaScript
import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
import {
DEPRECATED_CONFIG_SURFACES,
logLatency
} from "./chunk-5THXD6X5.js";
import {
isAtOrAboveHomeDir,
isWindowsPath,
nameMatchesMarkerGlob,
normalizeFilePath,
realpathOrResolve,
walkUpDirs
} from "./chunk-Q5U6FMDI.js";
// dist/clients/workspace-topology.js
import * as fs2 from "node:fs";
import * as os2 from "node:os";
import * as path2 from "node:path";
// dist/clients/config-locations.js
import * as fs from "node:fs";
import * as os from "node:os";
import * as path from "node:path";
// dist/clients/error-class.js
function errorClassName(error) {
return error instanceof Error ? error.name : "unknown error";
}
// dist/clients/config-locations.js
var CANONICAL_PROJECT_CONFIG_FILE = ".pi-lens.json";
var CANONICAL_GLOBAL_CONFIG_FILE = "config.json";
var LSP_NAMESPACE_KEY = "lsp";
var GLOBAL_SURFACE_PREFIX = "~/.pi-lens/";
var LEGACY_FILE_SURFACES = DEPRECATED_CONFIG_SURFACES.filter((row) => row.kind === "file").map((row) => row.surface);
var LEGACY_ROOT_LSP_KEYS = DEPRECATED_CONFIG_SURFACES.filter((row) => row.kind === "key").map((row) => row.surface);
function isLspScoped(relativePath) {
const base = path.posix.basename(relativePath.replace(/\\/g, "/"));
return base === "lsp.json" || base === "pi-lsp.json";
}
function legacyLocation(relativePath, surface) {
return {
relativePath,
surface,
legacy: true,
lspScoped: isLspScoped(relativePath)
};
}
var PROJECT_CONFIG_LOCATIONS = [
legacyLocation("pi-lens.json", "pi-lens.json"),
legacyLocation("pi-lsp.json", "pi-lsp.json"),
legacyLocation(path.posix.join(".pi-lens", "lsp.json"), ".pi-lens/lsp.json"),
{
relativePath: CANONICAL_PROJECT_CONFIG_FILE,
legacy: false,
lspScoped: false
}
];
var PROJECT_CONFIG_BASENAMES = PROJECT_CONFIG_LOCATIONS.filter((location) => !location.lspScoped).map((location) => location.relativePath).reverse();
var GLOBAL_CONFIG_LOCATIONS = [
legacyLocation("lsp.json", `${GLOBAL_SURFACE_PREFIX}lsp.json`),
{
relativePath: CANONICAL_GLOBAL_CONFIG_FILE,
legacy: false,
lspScoped: false
}
];
var DECLARED_LEGACY_FILE_SURFACES = [
...PROJECT_CONFIG_LOCATIONS,
...GLOBAL_CONFIG_LOCATIONS
].filter((location) => location.legacy).map((location) => location.surface);
function configSearchDirs(startDir, homeDir = os.homedir()) {
const dirs = [];
for (const dir of walkUpDirs(startDir)) {
if (isAtOrAboveHomeDir(dir, homeDir))
break;
dirs.push(dir);
}
return dirs;
}
function defaultGlobalConfigExists(file) {
try {
return fs.statSync(file).isFile();
} catch (error) {
if (error.code === "ENOENT")
return false;
throw error;
}
}
function agentConfigPathFor(agentDir) {
return isWindowsPath(agentDir) ? path.win32.join(path.win32.resolve(agentDir), "extensions", "pi-lens.json") : path.join(path.resolve(agentDir), "extensions", "pi-lens.json");
}
function resolveGlobalConfigLocation(options) {
const owned = options !== void 0;
const homeDir = options?.homeDir ?? os.homedir();
const legacyDefault = path.join(homeDir, ".pi-lens", CANONICAL_GLOBAL_CONFIG_FILE);
const override = process.env.PI_LENS_CONFIG_PATH;
if (override) {
return { path: path.resolve(override), source: "pi-lens-config-path" };
}
let probeError;
const probe = (file) => {
try {
return (options?.exists ?? defaultGlobalConfigExists)(file) ? "present" : "absent";
} catch (error) {
probeError = error;
return "error";
}
};
const agentDir = owned ? void 0 : process.env.PI_CODING_AGENT_DIR?.trim();
const agentPath = agentDir ? agentConfigPathFor(agentDir) : void 0;
const legacyProbe = probe(legacyDefault);
if (legacyProbe === "present") {
if (agentPath !== void 0 && probe(agentPath) === "present") {
return {
path: legacyDefault,
source: "legacy-default-existing",
shadowedPath: agentPath
};
}
return { path: legacyDefault, source: "legacy-default-existing" };
}
if (legacyProbe === "error") {
return {
path: legacyDefault,
source: "legacy-default-unprobed",
existsProbeFailed: {
path: legacyDefault,
errorClassName: errorClassName(probeError)
}
};
}
if (agentPath !== void 0) {
const agentProbe = probe(agentPath);
if (agentProbe === "present") {
return { path: agentPath, source: "pi-coding-agent-dir" };
}
if (agentProbe === "error") {
return {
path: agentPath,
source: "pi-coding-agent-dir-unprobed",
existsProbeFailed: {
path: agentPath,
errorClassName: errorClassName(probeError)
}
};
}
}
return { path: legacyDefault, source: "canonical-default" };
}
var memoizedGlobalConfigResolution;
function globalConfigEnvFingerprint() {
return JSON.stringify([
process.env.PI_LENS_CONFIG_PATH,
process.env.PI_CODING_AGENT_DIR
]);
}
function getProductionGlobalConfigResolution() {
const fingerprint = globalConfigEnvFingerprint();
if (memoizedGlobalConfigResolution?.fingerprint !== fingerprint) {
memoizedGlobalConfigResolution = {
fingerprint,
resolution: resolveGlobalConfigLocation()
};
}
return memoizedGlobalConfigResolution.resolution;
}
function getPiLensGlobalConfigPath(homeDir) {
return homeDir === void 0 ? getProductionGlobalConfigResolution().path : resolveGlobalConfigLocation({ homeDir }).path;
}
function isResolvedGlobalConfigPath(candidate) {
return recognizedGlobalConfigPaths().has(canonicalPathIdentity(candidate));
}
function canonicalPathIdentity(candidate) {
if (isWindowsPath(candidate)) {
return normalizeFilePath(path.win32.resolve(candidate));
}
return normalizeFilePath(realpathOrResolve(candidate));
}
var recognizedCache;
function recognizedGlobalConfigPaths() {
const fingerprint = globalConfigEnvFingerprint();
if (recognizedCache?.fingerprint !== fingerprint) {
const paths = /* @__PURE__ */ new Set();
const override = process.env.PI_LENS_CONFIG_PATH;
if (override)
paths.add(canonicalPathIdentity(path.resolve(override)));
paths.add(canonicalPathIdentity(path.join(os.homedir(), ".pi-lens", CANONICAL_GLOBAL_CONFIG_FILE)));
const agentDir = process.env.PI_CODING_AGENT_DIR?.trim();
if (agentDir)
paths.add(canonicalPathIdentity(agentConfigPathFor(agentDir)));
recognizedCache = { fingerprint, paths };
}
return recognizedCache.paths;
}
// dist/clients/freshness-cadence.js
var FRESHNESS_CADENCE_MS = 2e3;
// dist/clients/workspace-topology.js
var MAX_WALK_DEPTH = 64;
var PI_LENS_CONFIG_BASENAMES = PROJECT_CONFIG_BASENAMES;
var dirMarkerCache = /* @__PURE__ */ new Map();
var topologyDerivedCacheResets = [];
function registerWorkspaceTopologyReset(reset) {
topologyDerivedCacheResets.push(reset);
}
var walkCache = /* @__PURE__ */ new Map();
var TOPOLOGY_MAX_DIR_ENTRIES = 256;
var TOPOLOGY_MAX_WALK_ENTRIES = 512;
var TOPOLOGY_IDLE_EVICT_MS_DEFAULT = 20 * 6e4;
function topologyIdleEvictMs() {
const value = Number.parseInt(process.env.PI_LENS_WORKSPACE_TOPOLOGY_IDLE_EVICT_MS ?? "", 10);
return Number.isSafeInteger(value) && value > 0 ? value : TOPOLOGY_IDLE_EVICT_MS_DEFAULT;
}
function deleteDirMarker(key) {
const entry = dirMarkerCache.get(key);
if (entry?.idleTimer)
clearTimeout(entry.idleTimer);
dirMarkerCache.delete(key);
}
function deleteWalk(key) {
const entry = walkCache.get(key);
if (entry?.idleTimer)
clearTimeout(entry.idleTimer);
walkCache.delete(key);
}
function touchDirMarker(key, entry) {
entry.lastUsedAt = Date.now();
if (entry.idleTimer)
clearTimeout(entry.idleTimer);
const stamp = entry.lastUsedAt;
entry.idleTimer = setTimeout(() => {
if (dirMarkerCache.get(key) === entry && entry.lastUsedAt === stamp)
deleteDirMarker(key);
}, topologyIdleEvictMs());
entry.idleTimer.unref?.();
}
function touchWalk(key, entry) {
entry.lastUsedAt = Date.now();
if (entry.idleTimer)
clearTimeout(entry.idleTimer);
const stamp = entry.lastUsedAt;
entry.idleTimer = setTimeout(() => {
if (walkCache.get(key) === entry && entry.lastUsedAt === stamp)
deleteWalk(key);
}, topologyIdleEvictMs());
entry.idleTimer.unref?.();
}
function resetWorkspaceTopology() {
for (const key of dirMarkerCache.keys())
deleteDirMarker(key);
for (const key of walkCache.keys())
deleteWalk(key);
for (const reset of topologyDerivedCacheResets)
reset();
}
function safeDirMtimeMs(dir) {
try {
return fs2.statSync(dir).mtimeMs;
} catch {
return -1;
}
}
function safeIsFile(filePath) {
try {
return fs2.statSync(filePath).isFile();
} catch {
return false;
}
}
function getDirectoryMarkers(dir) {
const resolvedDir = path2.resolve(dir);
const dirMtimeMs = safeDirMtimeMs(resolvedDir);
const cached = dirMarkerCache.get(resolvedDir);
if (cached && cached.dirMtimeMs === dirMtimeMs) {
touchDirMarker(resolvedDir, cached);
return cached.markers;
}
let entries = [];
try {
entries = fs2.readdirSync(resolvedDir, { withFileTypes: true });
} catch {
entries = [];
}
const present = new Set(entries.map((e) => e.name));
const fileNames = new Set(entries.filter((entry2) => entry2.isFile() || entry2.isSymbolicLink()).map((entry2) => entry2.name));
const resolveMarker = (basename) => {
if (!present.has(basename))
return void 0;
const candidate = path2.join(resolvedDir, basename);
return safeIsFile(candidate) ? candidate : void 0;
};
const piLensConfigPath = resolveMarker(PI_LENS_CONFIG_BASENAMES[0]) ?? resolveMarker(PI_LENS_CONFIG_BASENAMES[1]);
const markers = {
dir: resolvedDir,
dirMtimeMs,
entryNames: present,
entryFileNames: fileNames,
piLensConfigPath,
tsconfigPath: resolveMarker("tsconfig.json"),
packageJsonPath: resolveMarker("package.json"),
pnpmWorkspaceYamlPath: resolveMarker("pnpm-workspace.yaml"),
cargoTomlPath: resolveMarker("Cargo.toml"),
goWorkPath: resolveMarker("go.work"),
chartYamlPath: resolveMarker("Chart.yaml")
};
const entry = { dirMtimeMs, markers, lastUsedAt: Date.now() };
const outgoing = dirMarkerCache.get(resolvedDir);
if (outgoing?.idleTimer !== void 0) {
clearTimeout(outgoing.idleTimer);
outgoing.idleTimer = void 0;
}
dirMarkerCache.set(resolvedDir, entry);
touchDirMarker(resolvedDir, entry);
while (dirMarkerCache.size > TOPOLOGY_MAX_DIR_ENTRIES) {
const victim = [...dirMarkerCache.entries()].sort(([, a], [, b]) => a.lastUsedAt - b.lastUsedAt)[0];
if (!victim)
break;
deleteDirMarker(victim[0]);
}
return markers;
}
function walkCacheKey(startDir, markerKey) {
return `${path2.resolve(startDir)}\0${markerKey}`;
}
function dirMtimesStillFresh(dirMtimes) {
return dirMtimes.every(({ dir, mtimeMs }) => safeDirMtimeMs(dir) === mtimeMs);
}
function dirMtimesStillFreshAsync(dirMtimes) {
return Promise.all(dirMtimes.map(({ dir }) => dirMtimeMsAsync(dir))).then((current) => dirMtimes.every(({ mtimeMs }, index) => current[index] === mtimeMs));
}
function dirMtimeMsAsync(dir) {
return fs2.promises.stat(dir).then((stats) => stats.mtimeMs, () => -1);
}
function dirMtimeRecordsAsync(dirs) {
return Promise.all(dirs.map((dir) => dirMtimeMsAsync(dir).then((mtimeMs) => ({ dir, mtimeMs }))));
}
function unknownDirMtimeRecords(dirs) {
return dirs.map((dir) => ({ dir, mtimeMs: Number.NaN }));
}
function walkToNearestMatch(startDir, cacheSuffix, matches, capMetadata, homeDir) {
const key = walkCacheKey(startDir, cacheSuffix);
const cached = walkCache.get(key);
if (cached) {
const startDirMtime = cached.dirMtimes[0];
const isFresh = cached.dir === void 0 ? startDirMtime !== void 0 && Date.now() - cached.walkedAtMs < FRESHNESS_CADENCE_MS && safeDirMtimeMs(startDirMtime.dir) === startDirMtime.mtimeMs : dirMtimesStillFresh(cached.dirMtimes);
if (isFresh) {
touchWalk(key, cached);
return cached.dir;
}
}
const dirMtimes = [];
let found;
let depth = 0;
for (const dir of walkUpDirs(startDir)) {
if (isAtOrAboveHomeDir(dir, homeDir))
break;
if (depth >= MAX_WALK_DEPTH) {
logLatency({
type: "phase",
filePath: startDir,
phase: "workspace-topology-walk-cap",
durationMs: 0,
metadata: { ...capMetadata, depth, homeDir }
});
break;
}
const markers = getDirectoryMarkers(dir);
dirMtimes.push({ dir, mtimeMs: markers.dirMtimeMs });
if (matches(markers)) {
found = dir;
break;
}
depth += 1;
}
const walkedAtMs = Date.now();
const entry = {
dir: found,
dirMtimes,
walkedAtMs,
lastUsedAt: walkedAtMs
};
const outgoing = walkCache.get(key);
if (outgoing?.idleTimer !== void 0) {
clearTimeout(outgoing.idleTimer);
outgoing.idleTimer = void 0;
}
walkCache.set(key, entry);
touchWalk(key, entry);
while (walkCache.size > TOPOLOGY_MAX_WALK_ENTRIES) {
const victim = [...walkCache.entries()].sort(([, a], [, b]) => a.lastUsedAt - b.lastUsedAt)[0];
if (!victim)
break;
deleteWalk(victim[0]);
}
return found;
}
function findNearestDirWithMarker(startDir, markerKey, homeDir = os2.homedir()) {
return walkToNearestMatch(startDir, markerKey, (markers) => Boolean(markers[markerKey]), { markerKey }, homeDir);
}
function hasBasenameMarker(markers, basename) {
if (basename.includes("/") || basename.includes("\\")) {
return fs2.existsSync(path2.join(markers.dir, basename));
}
if (basename.includes("*")) {
return [...markers.entryFileNames].some((entryName) => nameMatchesMarkerGlob(entryName, basename));
}
return markers.entryNames.has(basename);
}
function findNearestDirWithAnyBasename(startDir, basenames, homeDir = os2.homedir()) {
if (basenames.length === 0)
return void 0;
return walkToNearestMatch(startDir, `any:${basenames.join(String.fromCodePoint(1))}`, (markers) => basenames.some((basename) => hasBasenameMarker(markers, basename)), { basenames }, homeDir);
}
function findPiLensConfigMarkerInDir(dir) {
const markers = getDirectoryMarkers(dir);
if (!markers.piLensConfigPath)
return void 0;
if (isResolvedGlobalConfigPath(markers.piLensConfigPath))
return void 0;
const stat = (() => {
try {
return fs2.statSync(markers.piLensConfigPath);
} catch {
return void 0;
}
})();
if (!stat?.isFile())
return void 0;
return {
path: markers.piLensConfigPath,
dir: markers.dir,
mtimeMs: stat.mtimeMs,
size: stat.size
};
}
function findGoverningTsconfigDir(startDir, homeDir = os2.homedir()) {
return findNearestDirWithMarker(startDir, "tsconfigPath", homeDir);
}
function getWorkspaceManifestMarkers(dir) {
const markers = getDirectoryMarkers(dir);
return {
hasPnpmWorkspaceYaml: markers.pnpmWorkspaceYamlPath !== void 0,
hasGoWork: markers.goWorkPath !== void 0,
hasCargoToml: markers.cargoTomlPath !== void 0,
hasPackageJson: markers.packageJsonPath !== void 0
};
}
export {
errorClassName,
CANONICAL_PROJECT_CONFIG_FILE,
CANONICAL_GLOBAL_CONFIG_FILE,
LSP_NAMESPACE_KEY,
LEGACY_ROOT_LSP_KEYS,
PROJECT_CONFIG_LOCATIONS,
PROJECT_CONFIG_BASENAMES,
GLOBAL_CONFIG_LOCATIONS,
configSearchDirs,
getProductionGlobalConfigResolution,
getPiLensGlobalConfigPath,
isResolvedGlobalConfigPath,
canonicalPathIdentity,
FRESHNESS_CADENCE_MS,
registerWorkspaceTopologyReset,
resetWorkspaceTopology,
getDirectoryMarkers,
dirMtimesStillFresh,
dirMtimesStillFreshAsync,
dirMtimeRecordsAsync,
unknownDirMtimeRecords,
findNearestDirWithMarker,
findNearestDirWithAnyBasename,
findPiLensConfigMarkerInDir,
findGoverningTsconfigDir,
getWorkspaceManifestMarkers
};