Luigit
repositories / dotfiles

dotfiles

bugabingas dorkfiles

owned by admin

pi/agent/ultra/dynamic-extensions/catalog/security-review-writer/d0e991293c4407629bb3b19989f7e51429c04cdbe44d170cfd26c5f19bf2fcc6/index.ts

Raw
import type { ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
import type { ReviewWriteResult } from "./core.ts";

const EXTENSION_NAME = "security-review-writer";
const TOOL_NAME = "security_review_writer";

type PlainTextComponent = {
	setText(value: string): void;
	render(width: number): string[];
	invalidate(): void;
};

function plainText(initial: string): PlainTextComponent {
	let value = initial;
	return {
		setText(next) {
			value = next;
		},
		render(width) {
			return value.split("\n").map((line) => line.slice(0, Math.max(0, width)));
		},
		invalidate() {},
	};
}

function component(previous: unknown): PlainTextComponent {
	return previous !== null && typeof previous === "object" && "setText" in previous
		? previous as PlainTextComponent
		: plainText("");
}

function redactedPathShape(path: string): { kind: "absolute" | "relative"; length: number } {
	return { kind: /^([A-Za-z]:[\\/]|[\\/])/.test(path) ? "absolute" : "relative", length: path.length };
}

function errorCode(error: unknown): string {
	return typeof error === "object" && error !== null && "code" in error && typeof error.code === "string"
		? error.code
		: "UNEXPECTED";
}

async function emit(ctx: ExtensionContext, event: string, durationMs: number, context: unknown): Promise<void> {
	const { dynamicExtensionRevision, logDynamicExtensionEvent } = await import("./debug.ts");
	await logDynamicExtensionEvent({
		name: EXTENSION_NAME,
		revision: dynamicExtensionRevision(import.meta.url),
		ctx,
		event,
		durationMs,
		context,
	}).catch(() => undefined);
}

export default function dynamicExtension(pi: ExtensionAPI) {
	pi.registerTool({
		name: TOOL_NAME,
		label: "Security Review Writer",
		description: "Atomically create or overwrite one UTF-8 text file beneath the current project's ai-workspace/security-reviews directory. Relative paths are review-root-relative; absolute paths must already be beneath that root.",
		parameters: {
			type: "object",
			properties: {
				path: { type: "string", description: "Review-root-relative or contained absolute target file path." },
				text: { type: "string", description: "Complete UTF-8 text content to write atomically." },
			},
			required: ["path", "text"],
			additionalProperties: false,
		},
		async execute(_id, params, signal, _onUpdate, ctx) {
			const started = performance.now();
			try {
				const { writeSecurityReview } = await import("./core.ts");
				const result = await writeSecurityReview({ cwd: ctx.cwd, path: params.path, text: params.text, signal });
				await emit(ctx, "write_complete", performance.now() - started, {
					relativePath: result.relativePath,
					bytes: result.bytes,
					replaced: result.replaced,
				});
				return {
					content: [{
						type: "text" as const,
						text: `${result.replaced ? "Overwrote" : "Created"} ${result.relativePath} atomically (${result.bytes} UTF-8 bytes).`,
					}],
					details: result,
				};
			} catch (error) {
				if (signal?.aborted || (error instanceof Error && error.name === "AbortError")) throw error;
				await emit(ctx, "write_failed", performance.now() - started, {
					path: redactedPathShape(params.path),
					code: errorCode(error),
				});
				throw error;
			}
		},
		renderCall(args, _theme, context) {
			const text = component(context.lastComponent);
			text.setText(`${TOOL_NAME} ${args.path}`);
			return text;
		},
		renderResult(result, { expanded, isPartial }, _theme, context) {
			const text = component(context.lastComponent);
			if (isPartial) {
				text.setText("Writing review…");
				return text;
			}
			const details = result.details as ReviewWriteResult | undefined;
			if (details?.ok) {
				let rendered = details.replaced ? "✓ Review overwritten" : "✓ Review created";
				if (expanded) rendered += `\n${details.relativePath} · ${details.bytes} UTF-8 bytes · atomic rename`;
				text.setText(rendered);
				return text;
			}
			text.setText("Review write failed");
			return text;
		},
	});

	pi.on("session_start", () => {
		const active = pi.getActiveTools();
		if (!active.includes(TOOL_NAME)) pi.setActiveTools([...active, TOOL_NAME]);
	});
}