Initial commit: pygenium as git submodule
This commit is contained in:
76
src/index.ts
Normal file
76
src/index.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
/**
|
||||
* pygienium — code hygiene extension for pi.
|
||||
*
|
||||
* Entry point. Registers `/pygienium-help`, auto-registers one
|
||||
* `/pygienium-<check>` command per registered `CheckDefinition`, plus the
|
||||
* `all`/`resume`/`status`/`export` commands. Adding a check requires ONLY a new
|
||||
* file in `src/checks/` plus one `registerCheck(def)` call — no changes here.
|
||||
*
|
||||
* Check files in `src/checks/` are auto-discovered (every `.ts` except the
|
||||
* registry barrel), so they self-register at load time before commands bind.
|
||||
*
|
||||
* Pi loads this file via jiti at runtime (see `pi.extensions` in package.json).
|
||||
* The default export runs once per session; the factory is async so check
|
||||
* modules finish registering before command wiring.
|
||||
*
|
||||
* @module pygienium/index
|
||||
*/
|
||||
|
||||
import { readdir } from "node:fs/promises";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import type {
|
||||
ExtensionAPI,
|
||||
ExtensionContext,
|
||||
SessionStartEvent,
|
||||
} from "@earendil-works/pi-coding-agent";
|
||||
import { registerPygieniumCommands } from "./commands.js";
|
||||
|
||||
/** Startup hint mirrored after piolium's convention. */
|
||||
export const PYGIENIUM_STARTUP_HINT =
|
||||
"Pygienium loaded. Run /pygienium-help for available checks and flags.";
|
||||
|
||||
export { buildPygieniumHelpLines } from "./help.js";
|
||||
|
||||
/**
|
||||
* Import every `checks/*.ts` module (except the registry barrel) so each check
|
||||
* file's top-level `registerCheck(def)` call runs before command binding. This
|
||||
* is what makes adding a check require zero index.ts changes — drop a file,
|
||||
* it self-registers.
|
||||
*/
|
||||
async function loadCheckModules(): Promise<void> {
|
||||
const dir = join(dirname(fileURLToPath(import.meta.url)), "checks");
|
||||
let entries: string[];
|
||||
try {
|
||||
entries = await readdir(dir);
|
||||
} catch {
|
||||
return; // no checks dir (e.g. minimal install)
|
||||
}
|
||||
for (const entry of entries) {
|
||||
if (!entry.endsWith(".ts")) continue;
|
||||
if (entry === "registry.ts" || entry === "load.ts") continue;
|
||||
await import(`./checks/${entry}`);
|
||||
}
|
||||
}
|
||||
|
||||
export default async function pygieniumExtension(
|
||||
pi: ExtensionAPI,
|
||||
): Promise<void> {
|
||||
// Self-register every shipped check before wiring commands.
|
||||
await loadCheckModules();
|
||||
|
||||
registerPygieniumCommands((name, options) => {
|
||||
pi.registerCommand(name, {
|
||||
description: options.description,
|
||||
handler: options.handler,
|
||||
});
|
||||
});
|
||||
|
||||
pi.on(
|
||||
"session_start",
|
||||
async (_event: SessionStartEvent, ctx: ExtensionContext) => {
|
||||
if (!ctx.hasUI) return;
|
||||
ctx.ui.notify(PYGIENIUM_STARTUP_HINT, "info");
|
||||
},
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user