UNPKG

cmte

Version:

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

111 lines (94 loc) 3.09 kB
import { PathResolver, PathSegment } from './PathResolver'; import { ValidationError } from './errors'; import { IterationContext, Workflow } from './types'; export class VariableResolver { private outputs: Map<string, any>; private globals: Record<string, any>; private objectsForIteration: Record<string, any>; constructor(workflow: Workflow) { this.outputs = new Map(); this.globals = workflow.variables || {}; this.objectsForIteration = workflow.objectsForIteration || {}; } /** * Resolve a variable reference, handling both output paths and globals */ resolve(reference: string, context: IterationContext = {}): any { if (reference.startsWith('$')) { return this.resolveOutputPath(reference, context); } return this.resolveGlobalReference(reference); } /** * Register an output value at a specific path */ registerOutput(path: string, value: any, context: IterationContext = {}): void { const segments = PathResolver.parsePath(path); const phase = segments[0].name; if (!this.outputs.has(phase)) { this.outputs.set(phase, {}); } let current = this.outputs.get(phase); // Walk through segments except the last one for (let i = 1; i < segments.length - 1; i++) { const segment = segments[i]; const resolvedChoice = segment.choice ? PathResolver.resolveChoice(segment, context, this.objectsForIteration) : null; if (!current[segment.name]) { current[segment.name] = {}; } current = current[segment.name]; if (resolvedChoice) { if (!current[resolvedChoice]) { current[resolvedChoice] = {}; } current = current[resolvedChoice]; } } // Handle the last segment const lastSegment = segments[segments.length - 1]; const resolvedChoice = lastSegment.choice ? PathResolver.resolveChoice(lastSegment, context, this.objectsForIteration) : null; if (resolvedChoice) { if (!current[lastSegment.name]) { current[lastSegment.name] = {}; } current[lastSegment.name][resolvedChoice] = value; } else { current[lastSegment.name] = value; } } private resolveOutputPath(path: string, context: IterationContext): any { const segments = PathResolver.parsePath(path); const phase = segments[0].name; if (!this.outputs.has(phase)) { throw new ValidationError(`Phase '${phase}' not found`); } return PathResolver.walkPath( this.outputs.get(phase), segments.slice(1), context, this.objectsForIteration ); } private resolveGlobalReference(reference: string): any { if (!(reference in this.globals)) { throw new ValidationError(`Global variable '${reference}' not found`); } return this.globals[reference]; } /** * Get all outputs for a phase */ getPhaseOutputs(phase: string): any { return this.outputs.get(phase); } /** * Clear all outputs (useful for testing) */ clearOutputs(): void { this.outputs.clear(); } }