UNPKG

review-copilot

Version:

ReviewCopilot - AI-powered code review assistant with customizable prompts

183 lines (182 loc) 9.13 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.OpenAIProvider = void 0; const base_provider_1 = require("./base-provider"); const util_1 = __importDefault(require("util")); const ai_messages_1 = require("../constants/ai-messages"); const logger_1 = require("../utils/logger"); class OpenAIProvider extends base_provider_1.BaseProvider { constructor(config) { super(config); } async review(prompt, content) { try { logger_1.Logger.info('\n=== OpenAI Review Request ==='); logger_1.Logger.gray('Model: ' + this.config.model); logger_1.Logger.gray('BaseURL: ' + this.config.baseURL); logger_1.Logger.gray('API Key: ***[REDACTED]***'); logger_1.Logger.gray('Prompt: ' + prompt); logger_1.Logger.gray('Content Length: ' + content.length); logger_1.Logger.gray('Content Preview: ' + content.slice(0, 100) + '...'); if (!content.trim()) { logger_1.Logger.warning('Warning: Empty content provided'); return 'No content to review.'; } const messages = [ { role: 'system', content: ai_messages_1.SYSTEM_MESSAGES.CODE_REVIEW(this.config.reviewLanguage), }, { role: 'user', content: `${prompt}\n\nContent to review:\n${content}`, }, ]; const requestBody = { model: this.config.model, messages, temperature: 0.7, stream: false, }; logger_1.Logger.info('\n=== Request Details ==='); logger_1.Logger.gray('Request Body: ' + util_1.default.inspect({ ...requestBody, messages: requestBody.messages.map((msg) => ({ ...msg, content: msg.content ? msg.content.length > 100 ? msg.content.slice(0, 100) + '...' : msg.content : '[NO CONTENT]', })), }, { colors: true, depth: 2, maxArrayLength: 2, })); logger_1.Logger.info('\n=== Making API Call ==='); logger_1.Logger.gray('Request Config: ' + JSON.stringify({ baseURL: this.config.baseURL, model: requestBody.model, })); let response; try { response = await this.client.chat.completions.create(requestBody); } catch (apiError) { logger_1.Logger.error('\n=== API Call Failed ==='); if (apiError.response) { logger_1.Logger.gray('Response Type: ' + (apiError.response.headers?.['content-type'] || 'unknown')); logger_1.Logger.gray('Response Status: ' + apiError.response.status); logger_1.Logger.gray('Response Headers: ' + util_1.default.inspect(apiError.response.headers)); logger_1.Logger.gray('Response Body: ' + util_1.default.inspect(apiError.response.data)); if (typeof apiError.response.data === 'string' && apiError.response.data.includes('<!DOCTYPE html>')) { logger_1.Logger.error('\nReceived HTML response instead of JSON. This usually indicates:'); logger_1.Logger.warning('1. The baseURL might be incorrect or pointing to a web interface'); logger_1.Logger.warning('2. The proxy server might be returning an auth/error page'); logger_1.Logger.warning('3. The API endpoint might not be properly configured'); logger_1.Logger.warning('\nPlease verify:'); logger_1.Logger.warning('- The baseURL is a direct API endpoint (should end with /v1)'); logger_1.Logger.warning('- Your API key is correctly set and has proper permissions'); logger_1.Logger.warning("- If using a proxy, ensure it's correctly forwarding API requests"); } } throw apiError; } logger_1.Logger.info('\n=== Response Details ==='); logger_1.Logger.gray('Response Object: ' + util_1.default.inspect(response, { colors: true, depth: null, maxArrayLength: null, })); let parsedResponse; if (typeof response === 'string') { try { parsedResponse = JSON.parse(response); logger_1.Logger.info('\n=== Parsed Response ==='); logger_1.Logger.gray('Parsed Response: ' + util_1.default.inspect(parsedResponse, { colors: true, depth: null, maxArrayLength: null, })); } catch (parseError) { logger_1.Logger.error('\nError: Failed to parse response string'); logger_1.Logger.gray('Parse Error: ' + util_1.default.inspect(parseError)); throw new Error('Failed to parse OpenAI API response'); } } else { parsedResponse = response; } if (!parsedResponse || !parsedResponse.choices || parsedResponse.choices.length === 0) { logger_1.Logger.error('\nError: Invalid Response Format'); logger_1.Logger.gray('Response: ' + util_1.default.inspect(parsedResponse, { colors: true, depth: null })); throw new Error('Invalid response format from OpenAI API'); } const result = parsedResponse.choices[0]?.message?.content; if (!result) { logger_1.Logger.error('\nError: Empty Response Content'); logger_1.Logger.gray('Choice Object: ' + util_1.default.inspect(parsedResponse.choices[0], { colors: true, depth: null, })); throw new Error('Empty response content from OpenAI API'); } logger_1.Logger.success('\n=== Success ==='); logger_1.Logger.gray('Response Content: ' + result); return result; } catch (error) { logger_1.Logger.error('\n=== Error Details ==='); logger_1.Logger.error('Type: ' + (error instanceof Error ? error.constructor.name : typeof error)); if (error instanceof Error) { logger_1.Logger.error('Name: ' + error.name); logger_1.Logger.error('Message: ' + error.message); logger_1.Logger.error('Stack: ' + error.stack); const errorMessage = error.message; if (errorMessage.includes('401')) { throw new Error('OpenAI API authentication failed. Please check your API key and ensure it has the correct permissions.'); } else if (errorMessage.includes('404')) { throw new Error('OpenAI API endpoint not found. Please verify the baseURL configuration.'); } else if (errorMessage.includes('429')) { throw new Error('OpenAI API rate limit exceeded. Please check your API quota and try again later.'); } else if (errorMessage.includes('500')) { throw new Error('OpenAI API internal server error. Please try again later or contact support if the issue persists.'); } // Log any additional error properties const errorObj = error; if (errorObj.response) { logger_1.Logger.error('\nAPI Response Error:'); logger_1.Logger.gray('Status: ' + errorObj.response.status); logger_1.Logger.gray('Status Text: ' + errorObj.response.statusText); logger_1.Logger.gray('Headers: ' + util_1.default.inspect(errorObj.response.headers)); logger_1.Logger.gray('Data: ' + util_1.default.inspect(errorObj.response.data, { colors: true, depth: null, })); } } throw error; } } } exports.OpenAIProvider = OpenAIProvider;