/** * pi-codebase-reader — Smart AST-based file outlining + Explorer subagent. * * Overrides the built-in `read` tool to return structural outlines for large * files in supported languages (TypeScript, JavaScript, Python, Go, Rust, Solidity). * Registers the `explorer` subagent for use with EITHER * `@tintinweb/pi-subagents` OR `nicobailon/pi-subagents`. * * SHERLOC Integration: * - Registers `repo_tree` (filtered repository tree) and `connected_tree` * (import dependency graph) as pi tools. * - The Explorer agent's system prompt includes the SHERLOC bug-localization * protocol with structured diagnostic output format. * - Self-recovery mechanisms (loop detection, context management, etc.) * are available for tool-execution wrappers. * - Optional `/sherloc-judge` command scores findings via LLM-as-judge. * * Users install their preferred subagent library: * pi install npm:@tintinweb/pi-subagents * — or — * pi install npm:pi-subagents * * Commands: * /codebase-reader [on|off] [local|global] * /codebase-reader-model [local|global] * /codebase-reader-settings [global|local] * /codebase-reader-subagent [local|global] * /sherloc-judge */ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"; import { registerCommands } from "./commands.js"; import { loadConfig } from "./config.js"; import { ensureExplorerAgent, reinstallExplorerAgent, } from "./explorer-agent.js"; import { registerReadTool, detectHashlineEditPro } from "./read-tool.js"; import { registerRepotreeTool, registerConnectedTreeTool } from "./sherloc/tools.js"; import type { CodebaseReaderConfig } from "./types.js"; export default function (pi: ExtensionAPI) { // ---- Mutable state ---- let config = loadConfig(process.cwd()); let enabled = config.general.enabled; // ---- Config helpers ---- function getConfig(): CodebaseReaderConfig { return config; } function reloadConfig(): CodebaseReaderConfig { config = loadConfig(process.cwd()); enabled = config.general.enabled; return config; } function isEnabled(): boolean { return enabled; } function setEnabled(v: boolean): void { enabled = v; } // ---- Explorer agent file (write early so agent def exists) ---- const useShortRead = detectHashlineEditPro(); ensureExplorerAgent({ model: config.explorer.model, thinking: config.explorer.thinking, maxTurns: config.explorer.max_turns, useShortRead, }); // ---- Register SHERLOC tools ---- registerRepotreeTool(pi); registerConnectedTreeTool(pi); // ---- Session lifecycle — silently refresh agent file ---- pi.on("session_start", async (_event, ctx) => { config = loadConfig(ctx.cwd); enabled = config.general.enabled; reinstallExplorerAgent({ model: config.explorer.model, thinking: config.explorer.thinking, maxTurns: config.explorer.max_turns, useShortRead, }); }); // pi.on("session_shutdown", ...) intentionally removed: // Previously the agent was reinstalled on every shutdown, // but that caused unwanted side effects when the user exited pi. // ---- Register the smart read tool ---- registerReadTool(pi, { isEnabled, getConfig }); // ---- Register commands ---- registerCommands(pi, { getConfig, setEnabled, isEnabled, reloadConfig, }); }