import * as os from "node:os"; import * as path from "node:path"; export interface EnvironmentContext { workspaceRoot: string; currentDate: string; timezone: string; shell: { type: string; path: string; }; os: { platform: string; arch: string; release: string; type: string; }; runtime: { name: string; version: string; }; } export async function collectEnvironmentContext( cwd: string, ): Promise { const context: EnvironmentContext = { workspaceRoot: cwd, currentDate: new Date().toISOString().split("T")[0], timezone: Intl.DateTimeFormat().resolvedOptions().timeZone, shell: detectShell(), os: collectOsInfo(), runtime: detectRuntime(), }; return context; } function detectShell(): { type: string; path: string } { const shellPath = process.env.SHELL || ""; const shellType = path.basename(shellPath) || "unknown"; return { type: shellType, path: shellPath, }; } function collectOsInfo() { return { platform: os.platform(), arch: os.arch(), release: os.release(), type: os.type(), }; } function detectRuntime(): { name: string; version: string } { if (typeof Bun !== "undefined") { return { name: "Bun", version: Bun.version || "unknown", }; } return { name: "Node.js", version: process.version, }; } export function buildContextXml(context: EnvironmentContext): string { const lines: string[] = []; lines.push(""); lines.push(" "); lines.push(` ${escapeXml(context.workspaceRoot)}`); lines.push(" "); lines.push( ` ${escapeXml(context.shell.path)}`, ); lines.push(` ${context.currentDate}`); lines.push(` ${context.timezone}`); lines.push(" "); lines.push(` ${context.os.platform}`); lines.push(` ${context.os.arch}`); lines.push(` ${escapeXml(context.os.type)}`); lines.push(` ${escapeXml(context.os.release)}`); lines.push(" "); lines.push(" "); lines.push(` ${context.runtime.name}`); lines.push(` ${context.runtime.version}`); lines.push(" "); lines.push(""); return lines.join("\n"); } function escapeXml(value: string): string { return value .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); }