/** * Step 6 - Dynamic system prompt assembly * * Goal: * - split prompt content into stable and runtime sections * - inject environment context on every turn * - optionally include project memory from AGENT.md */ import os from "node:os"; import fs from "node:fs/promises"; import path from "node:path"; import { execFile } from "node:child_process"; import { promisify } from "node:util"; const execFileAsync = promisify(execFile); async function readAgentMd(cwd) { const filePath = path.join(cwd, "AGENT.md"); try { const content = await fs.readFile(filePath, "utf8"); return "# Source: " + filePath + "\n" + content.trim(); } catch { return ""; } } async function getGitSection(cwd) { try { const [branch, status] = await Promise.all([ execFileAsync("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd }), execFileAsync("git", ["status", "--short"], { cwd }), ]); return [ "- Git branch: " + branch.stdout.trim(), "- Git status:\n" + (status.stdout.trim() || "clean"), ].join("\n"); } catch { return "- Git: not available"; } } export async function buildSystemPrompt({ cwd, additionalInstructions = "" }) { const staticSection = [ "", "You are Easy Agent, a terminal-native coding assistant.", "Be concise, practical, and action-oriented.", "Prefer specialized tools before using Bash.", "Understand the code before changing it.", "", ].join("\n"); const dynamicSection = [ "", "- Current working directory: " + cwd, "- Current date: " + new Date().toISOString(), "- OS: " + os.platform() + " " + os.release() + " (" + os.arch() + ")", await getGitSection(cwd), additionalInstructions ? "- Session instructions:\n" + additionalInstructions : "", await readAgentMd(cwd), "", ] .filter(Boolean) .join("\n\n"); return staticSection + "\n\n" + dynamicSection; }