UNPKG

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
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 }); }