UNPKG

erosolar-cli

Version:

Unified AI agent framework for the command line - Multi-provider support with schema-driven tools, code intelligence, and transparent reasoning

136 lines 5.1 kB
import { readFileSync } from 'node:fs'; import { dirname, resolve } from 'node:path'; import { fileURLToPath } from 'node:url'; const MODULE_DIR = dirname(fileURLToPath(import.meta.url)); const DEFAULT_RULEBOOK_ROOT = resolve(MODULE_DIR, '..', '..'); const manifestCache = new Map(); const promptCache = new Map(); export function loadAgentRulebook(profile, options = {}) { // If inline manifest is provided, use it directly if (options.inline) { const manifest = options.inline; if (manifest.profile !== profile) { throw new Error(`Rulebook profile mismatch for ${profile}. Expected \"${profile}\" but inline manifest declares \"${manifest.profile}\".`); } return manifest; } // Otherwise load from file const root = options.root ?? DEFAULT_RULEBOOK_ROOT; const filePath = resolveRulebookPath(profile, root, options.file); const cacheKey = filePath; const cached = manifestCache.get(cacheKey); if (cached) { return cached; } const raw = readFileSync(filePath, 'utf8'); const manifest = JSON.parse(raw); if (manifest.profile !== profile) { throw new Error(`Rulebook profile mismatch for ${profile}. Expected \"${profile}\" but file declares \"${manifest.profile}\".`); } manifestCache.set(cacheKey, manifest); return manifest; } export function buildAgentRulebookPrompt(profile, options = {}) { // If inline, don't cache (since it might change) if (options.inline) { const manifest = loadAgentRulebook(profile, { inline: options.inline }); return formatAgentRulebook(manifest); } const root = options.root ?? DEFAULT_RULEBOOK_ROOT; const filePath = resolveRulebookPath(profile, root, options.file); const cacheKey = filePath; const cached = promptCache.get(cacheKey); if (cached) { return cached; } const manifest = loadAgentRulebook(profile, { root, file: options.file }); const prompt = formatAgentRulebook(manifest); promptCache.set(cacheKey, prompt); return prompt; } export function formatAgentRulebook(manifest) { const lines = []; const headerLabel = manifest.label || manifest.profile; lines.push(`${headerLabel} — rulebook version ${manifest.version} (contract ${manifest.contractVersion}).`); if (manifest.description) { lines.push(manifest.description.trim()); } if (manifest.globalPrinciples?.length) { lines.push('\nGLOBAL PRINCIPLES:'); for (const rule of manifest.globalPrinciples) { lines.push(formatRuleLine(rule)); } } for (const phase of manifest.phases) { const phaseSummary = [phase.label || phase.id]; if (phase.description) { phaseSummary.push(`– ${phase.description}`); } lines.push(`\nPHASE ${phase.id}: ${phaseSummary.join(' ')}`); if (phase.trigger) { lines.push(` Trigger: ${phase.trigger}`); } for (const step of phase.steps) { lines.push(formatStepLine(step)); } } return lines.filter(Boolean).join('\n'); } function resolveRulebookPath(profile, root, fileOverride) { const trimmedOverride = fileOverride?.trim(); if (trimmedOverride) { return resolve(root, trimmedOverride); } return resolve(root, 'agents', `${profile}.rules.json`); } function formatRuleLine(rule, indent = ' ') { const severity = rule.severity?.toUpperCase() ?? 'INFO'; const parts = [`[${severity}] (${rule.id}) ${rule.summary}`]; if (rule.detail) { parts.push(`— ${rule.detail}`); } if (rule.evidenceRequired) { parts.push(`Evidence: ${rule.evidenceRequired}`); } return `${indent}${parts.join(' ')}`; } function formatStepLine(step) { const details = []; if (step.intent) { details.push(step.intent); } if (step.description && step.description !== step.intent) { details.push(step.description); } const header = [` STEP ${step.id}: ${step.title}`]; if (details.length) { header.push(`(${details.join(' — ')})`); } const lines = [header.join(' ')]; if (step.entryCriteria?.length) { lines.push(` Entry: ${step.entryCriteria.join('; ')}`); } if (step.exitCriteria?.length) { lines.push(` Exit: ${step.exitCriteria.join('; ')}`); } if (step.allowedTools?.length) { lines.push(` Allowed tools: ${step.allowedTools.join(', ')}`); } if (step.blockedTools?.length) { lines.push(` Blocked tools: ${step.blockedTools.join(', ')}`); } if (step.notes?.length) { lines.push(` Notes: ${step.notes.join(' ')}`); } for (const rule of step.rules) { lines.push(formatRuleLine(rule, ' - ')); } if (step.subSteps?.length) { lines.push(' Sub-steps:'); for (const subStep of step.subSteps) { lines.push(formatStepLine(subStep).replace(/^ {2}/gm, ' ')); } } return lines.join('\n'); } //# sourceMappingURL=agentRulebook.js.map