context-loader.js
1 /** 2 * Context Loader Utility 3 * 4 * Loads and merges markdown context files for agent system. 5 * Each agent loads base.md + their role-specific context file(s). 6 */ 7 8 import fs from 'fs/promises'; 9 import path from 'path'; 10 import { fileURLToPath } from 'url'; 11 12 const __filename = fileURLToPath(import.meta.url); 13 const __dirname = path.dirname(__filename); 14 15 /** 16 * Load context files and merge them into a single string 17 * 18 * @param {string[]} contextFiles - Array of context filenames (e.g., ['base.md', 'developer.md']) 19 * @returns {Promise<string>} - Merged context content 20 * 21 * @example 22 * const context = await loadContextFiles(['base.md', 'developer.md']); 23 * // Returns ~25KB merged context for Developer Agent 24 */ 25 export async function loadContextFiles(contextFiles) { 26 if (!Array.isArray(contextFiles) || contextFiles.length === 0) { 27 throw new Error('contextFiles must be a non-empty array'); 28 } 29 30 const contextsDir = path.join(__dirname, '..', 'contexts'); 31 const contents = []; 32 33 for (const file of contextFiles) { 34 const filePath = path.join(contextsDir, file); 35 36 try { 37 const content = await fs.readFile(filePath, 'utf8'); 38 contents.push(content); 39 } catch (error) { 40 if (error.code === 'ENOENT') { 41 throw new Error(`Context file not found: ${file} (expected at ${filePath})`); 42 } 43 throw error; 44 } 45 } 46 47 // Merge with separators 48 return contents.join('\n\n---\n\n'); 49 } 50 51 /** 52 * Get the size of loaded context in bytes 53 * 54 * @param {string} context - Context string 55 * @returns {number} - Size in bytes 56 */ 57 export function getContextSize(context) { 58 return Buffer.byteLength(context, 'utf8'); 59 } 60 61 /** 62 * Get the size of loaded context in kilobytes 63 * 64 * @param {string} context - Context string 65 * @returns {number} - Size in KB (rounded to 1 decimal) 66 */ 67 export function getContextSizeKB(context) { 68 return Math.round((getContextSize(context) / 1024) * 10) / 10; 69 } 70 71 /** 72 * Load and validate context files, returning metadata 73 * 74 * @param {string[]} contextFiles - Array of context filenames 75 * @returns {Promise<{context: string, size: number, sizeKB: number, files: string[]}>} 76 * 77 * @example 78 * const { context, sizeKB } = await loadContextWithMetadata(['base.md', 'qa.md']); 79 * console.log(`Loaded ${sizeKB}KB context for QA Agent`); 80 */ 81 export async function loadContextWithMetadata(contextFiles) { 82 const context = await loadContextFiles(contextFiles); 83 const size = getContextSize(context); 84 const sizeKB = getContextSizeKB(context); 85 86 return { 87 context, 88 size, 89 sizeKB, 90 files: contextFiles, 91 }; 92 }