UNPKG

pi-lens

Version:

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

54 lines (53 loc) • 2.46 kB
/** * Shared progress-streaming helper for the long-running full/batch/directory * diagnostic scans (`lens_diagnostics mode=full`, `lsp_diagnostics`). Those runs * are opaque for minutes; this streams a throttled progress bar to the tool's * `onUpdate` callback so the agent/user sees movement. */ /** * For a tool's `compactRenderResult` summarizer: when the result is a streaming * progress partial (`details.phase === "scanning"`, emitted via `onUpdate` during * a full scan), return the bar to display — the joined content `text` (which * already holds `renderScanProgress` output), or a counts fallback. Returns * `null` for a normal (non-progress) result so the caller falls through to its * usual summary. Without this, the details-driven summarizer renders "0 * diagnostics" mid-scan and the bar never shows. */ export function scanningSummaryLine(details, text) { const d = details; if (d?.phase !== "scanning") return null; return text || `Scanning… ${d.completed ?? 0}/${d.total ?? 0}`; } /** A ≤20-char ASCII bar + counts, e.g. `Scanning… [████░░░░░░] 45/123 (37%)`. */ export function renderScanProgress(completed, total, label = "Scanning project diagnostics") { const pct = total > 0 ? Math.min(100, Math.round((completed / total) * 100)) : 0; const width = 20; const filled = Math.round((pct / 100) * width); const bar = "█".repeat(filled) + "░".repeat(Math.max(0, width - filled)); return `${label}… [${bar}] ${completed}/${total} (${pct}%)`; } /** * Build a throttled `(completed, total) => void` that streams the progress bar to * `onUpdate` — at most once per `throttleMs` (default 250ms, ~4×/s) plus the * final tick so the bar always lands on 100%. Returns `undefined` when the SDK * gave no callback, so callers can pass it straight through as an optional. */ export function makeProgressReporter(onUpdate, label, throttleMs = 250) { const emit = onUpdate; if (typeof emit !== "function") return undefined; let lastEmit = 0; return (completed, total) => { const now = Date.now(); if (completed < total && now - lastEmit < throttleMs) return; lastEmit = now; emit({ content: [ { type: "text", text: renderScanProgress(completed, total, label) }, ], details: { phase: "scanning", completed, total }, }); }; }