import { VERSION, type ExtensionAPI, type ExtensionContext, } from "@earendil-works/pi-coding-agent"; import { arch, hostname, platform, release } from "node:os"; const COMMAND_TIMEOUT_MS = 1500; const INFRA_ENV = "PI_RUNTIME_CONTEXT_INFRA"; const DEPLOYMENT_ENV = "PI_RUNTIME_CONTEXT_DEPLOYMENT"; type GitContext = { root?: string; branch?: string; detached?: true; dirty: boolean; }; type RuntimeContext = { date: string; time: string; timezone: string; cwd: string; git?: GitContext; os: string; node: string; pi: string; hostname?: string; docker?: string; kubernetes?: string; deployment?: string; }; function pad(value: number): string { return String(value).padStart(2, "0"); } function clock( now = new Date(), ): Pick { return { date: `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`, time: `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`, timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, }; } export function parseGitStatus( output: string, root?: string, ): GitContext | undefined { const head = output.match(/^# branch\.head (.+)$/m)?.[1]?.trim(); if (!head) return undefined; return { ...(root ? { root } : {}), ...(head === "(detached)" ? { detached: true } : { branch: head }), dirty: output .split("\n") .some((line) => line.length > 0 && !line.startsWith("# ")), }; } async function output( pi: ExtensionAPI, command: string, args: string[], cwd?: string, ): Promise { try { const result = await pi.exec(command, args, { ...(cwd ? { cwd } : {}), timeout: COMMAND_TIMEOUT_MS, }); if (result.code !== 0 || result.killed) return undefined; return result.stdout.trim() || undefined; } catch { return undefined; } } async function snapshot( pi: ExtensionAPI, ctx: ExtensionContext, ): Promise { const includeInfra = process.env[INFRA_ENV] === "1"; const [gitStatus, gitRoot, docker, kubernetes] = await Promise.all([ output(pi, "git", ["status", "--porcelain=v2", "--branch"], ctx.cwd), output(pi, "git", ["rev-parse", "--show-toplevel"], ctx.cwd), includeInfra ? output(pi, "docker", ["context", "show"]) : undefined, includeInfra ? output(pi, "kubectl", ["config", "current-context"]) : undefined, ]); const deployment = process.env[DEPLOYMENT_ENV]?.trim() || undefined; const git = gitStatus ? parseGitStatus(gitStatus, gitRoot) : undefined; return { ...clock(), cwd: ctx.cwd, ...(git ? { git } : {}), os: `${platform()} ${release()} (${arch()})`, node: process.version, pi: VERSION, ...(includeInfra ? { hostname: hostname() } : {}), ...(docker ? { docker } : {}), ...(kubernetes ? { kubernetes } : {}), ...(deployment ? { deployment } : {}), }; } function message(context: RuntimeContext, timestamp: number) { return { role: "custom" as const, customType: "pi-runtime-context", content: `Runtime context (ephemeral, observational only):\n${JSON.stringify(context)}`, display: false, timestamp, }; } export default function runtimeContext(pi: ExtensionAPI): void { let runContext: ReturnType | undefined; pi.on("session_start", () => { runContext = undefined; }); pi.on("agent_start", async (_event, ctx) => { runContext = undefined; const timestamp = Date.now(); runContext = message(await snapshot(pi, ctx), timestamp); }); pi.on("context", (event) => { if (!runContext) return; return { messages: [...event.messages, runContext] }; }); pi.on("agent_end", () => { runContext = undefined; }); }