/**
 * Escape a string for safe inclusion in a shell command passed to `sh -c`.
 * Wraps the value in single quotes and escapes any embedded single quotes.
 */
export function shellEscape(value) {
    return "'" + value.replace(/'/g, "'\\''") + "'";
}
const TEMPLATE_VARIABLE_PATTERN = /\{\{([\w][\w.\-]*)\}\}/g;
const STEP_OUTPUT_TEMPLATE_PATTERN = /\{\{(steps\.[\w\-]+\.output)\}\}/g;
const STEP_OUTPUT_REF_PATTERN = /^steps\.([\w\-]+)\.output$/;
export function resolveVariables(config, vars) {
    const resolved = structuredClone(config);
    for (const agent of resolved.agents) {
        if (agent.task) {
            agent.task = resolveTemplate(agent.task, vars);
        }
    }
    if (resolved.workflows) {
        for (const workflow of resolved.workflows) {
            for (const step of workflow.steps) {
                if (step.task) {
                    step.task = resolveTemplate(step.task, vars);
                }
                if (step.command) {
                    step.command = resolveTemplateForShell(step.command, vars);
                }
                if (step.params && typeof step.params === 'object') {
                    for (const key of Object.keys(step.params)) {
                        const value = step.params[key];
                        if (typeof value === 'string') {
                            step.params[key] = resolveTemplate(value, vars);
                        }
                    }
                }
            }
        }
    }
    return resolved;
}
export function resolveTemplate(template, context) {
    return template.replace(TEMPLATE_VARIABLE_PATTERN, (match, key) => {
        if (key.startsWith('steps.')) {
            return match;
        }
        const value = resolveDotPath(key, context);
        if (value === undefined) {
            throw new Error(`Unresolved variable: {{${key}}}`);
        }
        return String(value);
    });
}
/**
 * Like resolveTemplate but shell-escapes interpolated values.
 * Use this when the result will be passed to `sh -c` to prevent injection.
 */
export function resolveTemplateForShell(template, context) {
    return template.replace(TEMPLATE_VARIABLE_PATTERN, (match, key) => {
        if (key.startsWith('steps.')) {
            return match;
        }
        const value = resolveDotPath(key, context);
        if (value === undefined) {
            throw new Error(`Unresolved variable: {{${key}}}`);
        }
        return shellEscape(String(value));
    });
}
export function resolveDotPath(key, context) {
    if (!key.includes('.')) {
        return toTemplateScalar(context[key]);
    }
    const parts = key.split('.');
    let current = context;
    for (const part of parts) {
        if (current === null || current === undefined || typeof current !== 'object') {
            return undefined;
        }
        current = current[part];
    }
    return toTemplateScalar(current);
}
export function resolveStepOutputRef(ref, stepOutputs) {
    const normalizedRef = ref.startsWith('{{') && ref.endsWith('}}') ? ref.slice(2, -2).trim() : ref;
    const match = STEP_OUTPUT_REF_PATTERN.exec(normalizedRef);
    if (!match) {
        throw new Error(`Invalid step output reference: ${ref}`);
    }
    const stepOutput = stepOutputs.get(match[1]);
    if (stepOutput === undefined) {
        throw new Error(`Unresolved step output reference: ${ref}`);
    }
    return stepOutput;
}
export function interpolateStepTask(template, context) {
    const stepOutputs = buildStepOutputMap(context);
    return template.replace(STEP_OUTPUT_TEMPLATE_PATTERN, (match, ref) => {
        try {
            return resolveStepOutputRef(ref, stepOutputs);
        }
        catch {
            return match;
        }
    });
}
function buildStepOutputMap(context) {
    const stepOutputs = new Map();
    const steps = context.steps;
    if (!steps || typeof steps !== 'object') {
        return stepOutputs;
    }
    for (const [stepName, stepState] of Object.entries(steps)) {
        if (!stepState || typeof stepState !== 'object') {
            continue;
        }
        const output = toTemplateScalar(stepState.output);
        if (output !== undefined) {
            stepOutputs.set(stepName, String(output));
        }
    }
    return stepOutputs;
}
function toTemplateScalar(value) {
    if (value === undefined || value === null)
        return undefined;
    if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
        return value;
    }
    return String(value);
}
export class TemplateResolver {
    resolveVariables(config, vars) {
        return resolveVariables(config, vars);
    }
    interpolate(template, vars) {
        return resolveTemplate(template, vars);
    }
    resolveDotPath(key, vars) {
        return resolveDotPath(key, vars);
    }
    interpolateStepTask(template, context) {
        return interpolateStepTask(template, context);
    }
}
//# sourceMappingURL=template-resolver.js.map