UNPKG

cmte

Version:

Design by Committee™ except it's just you and LLMs

147 lines (138 loc) 3.97 kB
import logger from "../../utils/logger.js"; /** * Resolves references to task outputs using explicit path syntax */ export class TaskOutputResolver { constructor(config = {}) { this.outputs = new Map(); this.config = { strict: true, ...config }; } /** * Register an output for a task */ registerTaskOutput(phase, taskPath, output, iterations) { const phaseOutput = this.outputs.get(phase) || { name: phase, outputs: {}, iterations: {} }; // Always register the base output phaseOutput.outputs[taskPath] = output; // Register iteration outputs if provided if (iterations) { Object.entries(iterations).forEach(([iterationKey, value]) => { phaseOutput.iterations = phaseOutput.iterations || {}; phaseOutput.iterations[iterationKey] = { name: `${phase}[${iterationKey}]`, outputs: { [taskPath]: value } }; }); } this.outputs.set(phase, phaseOutput); logger.debug(`Registered output for task ${taskPath} in phase ${phase}`, { output }); } /** * Parse a reference string into a TaskOutputReference * Format: $phase.set['iteration'].subset['iteration'].task['iteration'] */ parseReference(ref) { // Match the basic structure const basicMatch = ref.match(/^\$([^.]+)\.([^.[\]]+)(?:\['([^']+)'\])?(?:\.([^.[\]]+)(?:\['([^']+)'\])?)?\.([^.[\]]+)(?:\['([^']+)'\])?$/); if (!basicMatch) { return null; } const [, phase, set, setIter, subset, subsetIter, task, taskIter] = basicMatch; const reference = { phase, set, task }; if (subset) { reference.subset = subset; } if (setIter || subsetIter || taskIter) { reference.iterations = {}; if (setIter) reference.iterations.set = setIter; if (subsetIter) reference.iterations.subset = subsetIter; if (taskIter) reference.iterations.task = taskIter; } return reference; } /** * Build a task path from a reference */ buildTaskPath(ref) { const parts = [ref.set]; if (ref.subset) parts.push(ref.subset); parts.push(ref.task); return parts.join('.'); } /** * Resolve a reference to a task's output */ resolveReference(ref) { // Parse the reference const reference = this.parseReference(ref); if (!reference) { return { value: '', success: false, error: `Invalid reference format: ${ref}` }; } // Get the phase output const phaseOutput = this.outputs.get(reference.phase); if (!phaseOutput) { return { value: '', success: false, error: `Phase not found: ${reference.phase}` }; } const taskPath = this.buildTaskPath(reference); // Handle iterations if specified if (reference.iterations) { // Find the most specific iteration that matches const iterationKeys = Object.entries(reference.iterations).map(([level, value]) => `${level}:${value}`).join('.'); if (!phaseOutput.iterations?.[iterationKeys]) { return { value: '', success: false, error: `No output found for iterations ${iterationKeys} in phase ${reference.phase}` }; } const output = phaseOutput.iterations[iterationKeys].outputs[taskPath]; if (!output) { return { value: '', success: false, error: `Task ${taskPath} not found in iterations ${iterationKeys} of phase ${reference.phase}` }; } return { value: output, success: true }; } // Handle direct task reference const output = phaseOutput.outputs[taskPath]; if (!output) { return { value: '', success: false, error: `Task ${taskPath} not found in phase ${reference.phase}` }; } return { value: output, success: true }; } }