UNPKG

pi-lens

Version:

Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo

88 lines (87 loc) • 4.33 kB
/** * Subagent light mode (#449 slice 0; broadened #507). * * Two known subagent-spawning ecosystems set different env vocabularies in * every spawned child's environment: * * - nicobailon/pi-subagents sets `PI_SUBAGENT_CHILD=1` unconditionally (plus * `PI_SUBAGENT_RUN_ID` / `PI_SUBAGENT_CHILD_AGENT` for best-effort identity). * - avtc-pi-subagent (the spawn engine under avtc-pi-feature-flow) is the same * execution model — real child-process `pi --mode rpc` / `--mode json -p` * spawns, full env inheritance — but never sets `PI_SUBAGENT_CHILD`. It sets * `PI_SUBAGENT_CHILD_AGENT` + `PI_SUBAGENT_PARENT_PID` instead (#507, * grep-verified against avtc-pi-subagent@1.0.3). * * Every child currently loads pi-lens fully by default, so a fan-out of N * subagents pays N full LSP pre-warms + N sets of heavyweight startup scans * in the same cwd — mostly wasted on short-lived task agents. * * Detection requires the avtc PAIR (`PI_SUBAGENT_CHILD_AGENT` AND * `PI_SUBAGENT_PARENT_PID`, both non-empty) rather than either var alone — * deliberate false-positive protection, since a lone var set by some * unrelated tool must not trigger light mode. * * This module only classifies the session; it does not change any behavior * itself. Callers (`runtime-session.ts`) gate the LSP pre-warm and the seven * heavyweight external-CLI startup scans on `isSubagentSession()`. Per-edit * LSP dispatch is untouched — light mode must not disable diagnostics. * * Escape hatch: `PI_LENS_SUBAGENT_FULL=1` forces full (non-light) behavior * even inside a detected subagent session, for either vocabulary. * * Follows the lazy-memoized-config house style (see `runtime-config.ts` / * `slow-fs.ts`): env values are read lazily at call time, not module load. */ /** Lazily computed once per process (until `_resetSubagentModeForTests`), * matching the memoized-getter house style. */ let cachedClassification; function classifySubagentSession() { if (cachedClassification !== undefined) return cachedClassification; if (process.env.PI_SUBAGENT_CHILD === "1") { cachedClassification = { isSubagent: true, marker: "pi-subagents" }; return cachedClassification; } const childAgent = process.env.PI_SUBAGENT_CHILD_AGENT || undefined; const parentPid = process.env.PI_SUBAGENT_PARENT_PID || undefined; if (childAgent !== undefined && parentPid !== undefined) { cachedClassification = { isSubagent: true, marker: "avtc-pi-subagent" }; return cachedClassification; } cachedClassification = { isSubagent: false }; return cachedClassification; } /** True iff pi-lens is running inside a detected subagent child `pi` process * (nicobailon/pi-subagents' `PI_SUBAGENT_CHILD=1`, or avtc-pi-subagent's * `PI_SUBAGENT_CHILD_AGENT` + `PI_SUBAGENT_PARENT_PID` pair), and the caller * has not forced full behavior via the escape hatch. */ export function isSubagentSession() { if (process.env.PI_LENS_SUBAGENT_FULL === "1") return false; return classifySubagentSession().isSubagent; } /** * Best-effort identity of the current subagent, read from the env vars the * detected extension sets alongside its subagent marker. Returns `undefined` * when neither identity var is present (e.g. not a subagent session, or a * future extension that doesn't set them). */ export function getSubagentIdentity() { const runId = process.env.PI_SUBAGENT_RUN_ID || undefined; const agentName = process.env.PI_SUBAGENT_CHILD_AGENT || undefined; if (runId === undefined && agentName === undefined) return undefined; const { marker } = classifySubagentSession(); return { runId, agentName, marker }; } /** Human-readable degradation notice surfaced once per session when subagent * light mode engages, so a subagent never sees a silently-empty scan result. */ export function subagentLightModeNotice() { return "subagent session — skipped background code-quality scans (set PI_LENS_SUBAGENT_FULL=1 to override)"; } /** Test-only: clears the memoized classification so tests can flip env vars * between cases (matching the `_resetForTests` convention used by * `runtime-config.ts` / `slow-fs.ts`). */ export function _resetSubagentModeForTests() { cachedClassification = undefined; }