cmte
Version:
Design by Committee™ except it's just you and LLMs
110 lines (102 loc) • 3.9 kB
JavaScript
import { resolvePath } from "../utils/fs.js";
import { logger } from "../utils/logger.js";
import path from 'path';
import { TemplateRenderer } from "../templates/renderer.js";
/**
* Default model configuration for the two-phase processor
*/
export const defaultModelConfig = {
thinkingModel: process.env.THINKING_MODEL || 'claude-3-7-sonnet-latest',
responseModel: process.env.RESPONSE_MODEL || 'claude-3-7-sonnet-latest',
temperature: parseFloat(process.env.TEMPERATURE || '0.7'),
maxTokens: parseInt(process.env.MAX_TOKENS || '4000', 10),
useXML: process.env.USE_XML === 'true' // Add XML support option
};
/**
* Creates the output paths for the two-phase processor
* @param config Two-phase processor configuration
* @returns Resolved output paths
*/
export function resolveOutputPaths(config) {
const resolvedPaths = resolvePath(config.outputPath, config.context);
logger.debug('Resolved output paths', {
thinking: resolvedPaths.thinking,
response: resolvedPaths.response
});
return resolvedPaths;
}
/**
* Merges the default model configuration with the provided configuration
* @param modelConfig Partial model configuration
* @returns Complete model configuration
*/
export function mergeModelConfig(modelConfig) {
if (!modelConfig) {
return defaultModelConfig;
}
return {
thinkingModel: modelConfig.thinkingModel || defaultModelConfig.thinkingModel,
responseModel: modelConfig.responseModel || defaultModelConfig.responseModel,
temperature: modelConfig.temperature !== undefined ? modelConfig.temperature : defaultModelConfig.temperature,
maxTokens: modelConfig.maxTokens !== undefined ? modelConfig.maxTokens : defaultModelConfig.maxTokens,
useXML: modelConfig.useXML !== undefined ? modelConfig.useXML : defaultModelConfig.useXML
};
}
/**
* Creates a configuration for the thinking phase
* @param config Two-phase processor configuration
* @returns Configuration for the thinking phase
*/
export function createThinkingConfig(config) {
const mergedConfig = mergeModelConfig(config.modelConfig);
return {
model: mergedConfig.thinkingModel,
temperature: mergedConfig.temperature,
maxTokens: mergedConfig.maxTokens,
useXML: mergedConfig.useXML
};
}
/**
* Creates a configuration for the response phase
* @param config Two-phase processor configuration
* @returns Configuration for the response phase
*/
export function createResponseConfig(config) {
const mergedConfig = mergeModelConfig(config.modelConfig);
return {
model: mergedConfig.responseModel,
temperature: mergedConfig.temperature,
maxTokens: mergedConfig.maxTokens,
useXML: mergedConfig.useXML
};
}
/**
* Renders a template file with the given context and optional file collections
* @param templatePath Template file path
* @param context Context for variables
* @param fileContext Optional file collections
* @param useXML Whether to convert to XML format
* @param isLLMResponse Whether this is an LLM response being reused
* @returns Rendered template content
*/
export async function renderTemplate(templatePath, context, fileContext, useXML, isLLMResponse) {
logger.debug(`Rendering template: ${templatePath}`, {
contextKeys: Object.keys(context),
hasFileContext: !!fileContext,
fileCollections: fileContext ? Object.keys(fileContext) : [],
useXML,
isLLMResponse
});
// Use the enhanced template renderer for all cases to ensure consistent handling
const templateDir = path.dirname(templatePath);
const renderer = new TemplateRenderer(context, templateDir, useXML);
// Register file collections if provided
if (fileContext) {
renderer.registerCollections(fileContext);
}
// Render the template with LLM response handling
const templateName = path.basename(templatePath);
return renderer.renderTemplate(templateName, {
isLLMResponse
});
}