vibe-coder-mcp
Version:
Production-ready MCP server with complete agent integration, multi-transport support, and comprehensive development automation tools for AI-assisted workflows.
133 lines (132 loc) • 6.29 kB
JavaScript
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
import { performFormatAwareLlmCall, intelligentJsonParse } from './llmHelper.js';
import { ValidationError } from './errors.js';
import logger from '../logger.js';
export async function performSchemaAwareLlmCall(prompt, systemPrompt, config, logicalTaskName, zodSchema, options = {}) {
const startTime = Date.now();
const { maxRetries = 3, temperature = 0.1, includeSchemaInPrompt = true, includeExamples = true, customErrorMessages = [] } = options;
let lastError;
let rawResponse = '';
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const enhancedPrompt = buildSchemaGuidedPrompt(prompt, zodSchema, {
includeSchema: includeSchemaInPrompt,
includeExamples,
attempt,
previousErrors: attempt > 1 ? [lastError?.message || 'Previous attempt failed validation'] : [],
customErrorMessages
});
logger.debug({
logicalTaskName,
attempt,
maxRetries,
promptLength: enhancedPrompt.length,
includeSchemaInPrompt,
includeExamples
}, 'Performing schema-aware LLM call');
rawResponse = await performFormatAwareLlmCall(enhancedPrompt, systemPrompt, config, logicalTaskName, 'json', undefined, temperature);
const parsed = intelligentJsonParse(rawResponse, `${logicalTaskName}-attempt-${attempt}`);
const validated = zodSchema.parse(parsed);
const processingTime = Date.now() - startTime;
logger.info({
logicalTaskName,
attempt,
success: true,
processingTimeMs: processingTime,
hadRetries: attempt > 1,
responseLength: rawResponse.length
}, 'Schema-aware LLM call succeeded');
return {
data: validated,
attempts: attempt,
hadRetries: attempt > 1,
processingTimeMs: processingTime,
rawResponse
};
}
catch (error) {
lastError = error;
logger.warn({
logicalTaskName,
attempt,
maxRetries,
error: error instanceof Error ? error.message : String(error),
isZodError: error instanceof z.ZodError,
zodIssues: error instanceof z.ZodError ? error.issues : undefined
}, 'Schema-aware LLM call attempt failed');
if (attempt === maxRetries) {
break;
}
if (error instanceof z.ZodError) {
const validationErrors = error.issues.map(issue => `${issue.path.join('.')}: ${issue.message}`).join('; ');
customErrorMessages.push(`Validation failed: ${validationErrors}`);
}
}
}
const processingTime = Date.now() - startTime;
throw new ValidationError(`Schema-aware LLM call failed after ${maxRetries} attempts for task: ${logicalTaskName}`, undefined, {
lastError: lastError?.message,
attempts: maxRetries,
processingTimeMs: processingTime,
rawResponse: rawResponse.substring(0, 500)
});
}
function buildSchemaGuidedPrompt(originalPrompt, zodSchema, options) {
const { includeSchema, includeExamples, attempt, previousErrors, customErrorMessages } = options;
let enhancedPrompt = originalPrompt;
if (attempt > 1) {
enhancedPrompt += `\n\n⚠️ RETRY ATTEMPT ${attempt}:\n`;
if (previousErrors.length > 0) {
enhancedPrompt += `Previous attempt failed with: ${previousErrors.join('; ')}\n`;
}
if (customErrorMessages.length > 0) {
enhancedPrompt += `Specific issues to fix: ${customErrorMessages.join('; ')}\n`;
}
enhancedPrompt += `Please ensure your response exactly matches the required schema.\n`;
}
if (includeSchema) {
try {
const jsonSchema = zodToJsonSchema(zodSchema, {
name: 'ResponseSchema',
$refStrategy: 'none'
});
enhancedPrompt += `\n\n📋 REQUIRED JSON SCHEMA:\n`;
enhancedPrompt += `Your response must be valid JSON that exactly matches this schema:\n\n`;
enhancedPrompt += `\`\`\`json\n${JSON.stringify(jsonSchema, null, 2)}\n\`\`\`\n`;
}
catch (error) {
logger.warn({ error }, 'Failed to convert Zod schema to JSON schema');
}
}
enhancedPrompt += `\n\n✅ CRITICAL REQUIREMENTS:\n`;
enhancedPrompt += `1. Response must be valid JSON only - no markdown, no explanations, no code blocks\n`;
enhancedPrompt += `2. All required fields must be present and correctly typed\n`;
enhancedPrompt += `3. Use double quotes for all strings\n`;
enhancedPrompt += `4. No trailing commas\n`;
enhancedPrompt += `5. No comments in JSON\n`;
enhancedPrompt += `6. Ensure all nested objects and arrays are properly structured\n`;
if (includeExamples) {
enhancedPrompt += `\n\n💡 FORMATTING EXAMPLE:\n`;
enhancedPrompt += `Your response should look like this structure (with your actual data):\n`;
enhancedPrompt += `\`\`\`json\n{\n "field1": "value1",\n "field2": {\n "nested": "value"\n },\n "field3": ["item1", "item2"]\n}\n\`\`\`\n`;
}
enhancedPrompt += `\n\nJSON Response:`;
return enhancedPrompt;
}
export async function performModuleSelectionCall(prompt, systemPrompt, config, zodSchema) {
return performSchemaAwareLlmCall(prompt, systemPrompt, config, 'fullstack_starter_kit_module_selection', zodSchema, {
maxRetries: 3,
temperature: 0.1,
includeSchemaInPrompt: true,
includeExamples: true
});
}
export async function performTemplateGenerationCall(prompt, systemPrompt, config, zodSchema) {
return performSchemaAwareLlmCall(prompt, systemPrompt, config, 'fullstack_starter_kit_dynamic_yaml_module_generation', zodSchema, {
maxRetries: 2,
temperature: 0.2,
includeSchemaInPrompt: true,
includeExamples: false
});
}