repositories / dotfiles
dotfiles
bugabingas dorkfiles
owned by admin
pi/agent/ultra/dynamic-extensions/catalog/security-review-writer/d0e991293c4407629bb3b19989f7e51429c04cdbe44d170cfd26c5f19bf2fcc6/debug.ts
Rawimport { appendFile, mkdir, open, stat } from "node:fs/promises";
import { homedir } from "node:os";
import { basename, dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
const LOG_LIMIT_BYTES = 1024 * 1024;
const MARKER_RESERVE_BYTES = 512;
const VALUE_LIMIT = 12_000;
function cacheRoot(): string {
if (process.platform === "win32")
return process.env.LOCALAPPDATA ?? join(homedir(), "AppData", "Local");
if (process.platform === "darwin")
return join(homedir(), "Library", "Caches");
return process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache");
}
function bounded(value: unknown): unknown {
let encoded: string;
try {
encoded = JSON.stringify(value);
} catch {
encoded = String(value);
}
return encoded.length <= VALUE_LIMIT
? value
: { truncated: true, preview: encoded.slice(0, VALUE_LIMIT) };
}
export function dynamicExtensionRevision(moduleUrl: string): string {
return basename(dirname(fileURLToPath(moduleUrl)));
}
export function dynamicExtensionLogPath(
sessionId: string,
extensionName: string,
): string {
return join(
cacheRoot(),
"pi",
"ultra",
"dynamic-extensions",
"logs",
sessionId,
`${extensionName}.jsonl`,
);
}
async function hasTruncationMarker(path: string, size: number): Promise<boolean> {
if (size === 0) return false;
const handle = await open(path, "r");
try {
const length = Math.min(size, 1024);
const bytes = Buffer.alloc(length);
await handle.read(bytes, 0, length, size - length);
return bytes.toString("utf8").includes('"event":"log_truncated"');
} finally {
await handle.close();
}
}
export async function logDynamicExtensionEvent(args: {
name: string;
revision: string;
ctx: ExtensionContext;
event: string;
durationMs?: number;
context?: unknown;
}): Promise<void> {
const sessionId = args.ctx.sessionManager.getSessionId();
const path = dynamicExtensionLogPath(sessionId, args.name);
await mkdir(dirname(path), { recursive: true });
const size = await stat(path).then((value) => value.size, () => 0);
if (size >= LOG_LIMIT_BYTES) return;
const record = {
timestamp: new Date().toISOString(),
extension: { name: args.name, revision: args.revision },
childSessionId: sessionId,
event: args.event,
...(args.durationMs === undefined ? {} : { durationMs: args.durationMs }),
...(args.context === undefined ? {} : { context: bounded(args.context) }),
};
const line = `${JSON.stringify(record)}\n`;
if (
size < LOG_LIMIT_BYTES - MARKER_RESERVE_BYTES &&
size + Buffer.byteLength(line) <= LOG_LIMIT_BYTES - MARKER_RESERVE_BYTES
) {
await appendFile(path, line, "utf8");
return;
}
if (await hasTruncationMarker(path, size)) return;
const marker = {
timestamp: new Date().toISOString(),
extension: { name: args.name, revision: args.revision },
childSessionId: sessionId,
event: "log_truncated",
context: { limitBytes: LOG_LIMIT_BYTES },
};
await appendFile(path, `${JSON.stringify(marker)}\n`, "utf8");
}