UNPKG

autoagent-cli

Version:

Run autonomous AI agents using Claude or Gemini for task execution

257 lines (256 loc) 13.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.runReflection = runReflection; const promises_1 = require("fs/promises"); const path_1 = require("path"); const factory_js_1 = require("../../providers/factory.js"); async function runReflection(options) { let iterations = 0; let originalContent = null; let fileModified = false; try { try { await (0, promises_1.access)(options.specFile, promises_1.constants.F_OK); } catch (error) { throw new Error(`Spec file not found: ${options.specFile}`); } let specContent; try { specContent = await (0, promises_1.readFile)(options.specFile, 'utf-8'); originalContent = specContent; } catch (error) { if (error instanceof Error && error.message.includes('ENOENT')) { throw new Error(`Spec file does not exist: ${options.specFile}`); } throw error; } if (options.backupOriginal === true) { const backupPath = `${options.specFile}.backup`; try { const dir = (0, path_1.dirname)(options.specFile); await (0, promises_1.access)(dir, promises_1.constants.W_OK); await (0, promises_1.writeFile)(backupPath, originalContent); } catch (error) { if (error instanceof Error && (error.message.includes('EACCES') || error.message.includes('permission'))) { throw new Error('Failed to create backup: permission denied'); } throw new Error(`Failed to create backup: ${error instanceof Error ? error.message : 'Unknown error'}`); } } let provider = await factory_js_1.ProviderFactory.getProvider(options.provider); let actualProviderName = provider.name; if ('getRateLimits' in provider && typeof provider.getRateLimits === 'function') { provider.getRateLimits(); } const maxIterations = options.maxIterations ?? 3; const improvementThreshold = options.improvementThreshold ?? 8; let finalScore = 0; const improvements = []; for (let i = 1; i <= maxIterations; i++) { if (i > 1) { try { await (0, promises_1.access)(options.specFile, promises_1.constants.F_OK); specContent = await (0, promises_1.readFile)(options.specFile, 'utf-8'); } catch (error) { iterations = i - 1; throw new Error(`Spec file not found during reflection: ${options.specFile}`); } } if ('isAvailable' in provider && typeof provider.isAvailable === 'function') { const available = await provider.isAvailable(); if (!available) { const fallbackProviderName = provider.name === 'claude' ? 'gemini' : 'claude'; const fallbackProvider = await factory_js_1.ProviderFactory.getProvider(fallbackProviderName); provider = fallbackProvider; actualProviderName = fallbackProvider.name; } } if ('generateCompletion' in provider && typeof provider.generateCompletion === 'function') { let reflectionResponse; try { if (provider.generateCompletion !== undefined) { reflectionResponse = await provider.generateCompletion(`Reflection iteration ${i}`); } } catch (error) { if (error instanceof Error && error.message.toLowerCase().includes('interrupt')) { iterations = i; throw error; } if (error instanceof Error && error.message.includes('re-analyze')) { iterations = i; throw error; } const fallbackProviderName = provider.name === 'claude' ? 'gemini' : 'claude'; try { const fallbackProvider = await factory_js_1.ProviderFactory.getProvider(fallbackProviderName); provider = fallbackProvider; actualProviderName = fallbackProvider.name; if (fallbackProvider.generateCompletion) { reflectionResponse = await fallbackProvider.generateCompletion(`Reflection iteration ${i}`); } } catch (fallbackError) { throw error; } } if (reflectionResponse && reflectionResponse.content) { const scoreMatch = reflectionResponse.content.match(/(\d+(?:\.\d+)?)\s*\/\s*10/i) || reflectionResponse.content.match(/Score:\s*(\d+(?:\.\d+)?)/i); if (scoreMatch && scoreMatch[1] !== undefined) { const score = parseFloat(scoreMatch[1]); if (!isNaN(score)) { finalScore = score; } } else { try { if (provider.generateCompletion) { const retryResponse = await provider.generateCompletion(`Reflection iteration ${i} (retry)`); const retryScoreMatch = retryResponse.content.match(/(\d+(?:\.\d+)?)\s*\/\s*10/i) || retryResponse.content.match(/Score:\s*(\d+(?:\.\d+)?)/i); if (retryScoreMatch && retryScoreMatch[1] !== undefined) { const retryScore = parseFloat(retryScoreMatch[1]); if (!isNaN(retryScore)) { finalScore = retryScore; reflectionResponse = retryResponse; } } } } catch (retryError) { } } const changeMatches = reflectionResponse.content.match(/improvement|change|add|modify/gi) ?? []; const changeCount = changeMatches.length > 0 ? changeMatches.length : 1; improvements.push({ iteration: i, score: finalScore, changes: changeCount }); if (finalScore >= improvementThreshold) { iterations = i; break; } let improvementResponse; if ('isAvailable' in provider && typeof provider.isAvailable === 'function') { const available = await provider.isAvailable(); if (!available) { const fallbackProviderName = provider.name === 'claude' ? 'gemini' : 'claude'; const fallbackProvider = await factory_js_1.ProviderFactory.getProvider(fallbackProviderName); provider = fallbackProvider; actualProviderName = fallbackProvider.name; } } try { if (provider.generateCompletion) { improvementResponse = await provider.generateCompletion(`Apply improvements for iteration ${i}`); } } catch (error) { if (error instanceof Error && error.message.toLowerCase().includes('interrupt')) { iterations = i; throw error; } if (error instanceof Error && error.message.includes('re-analyze')) { iterations = i; throw error; } const fallbackProviderName = provider.name === 'claude' ? 'gemini' : 'claude'; try { const fallbackProvider = await factory_js_1.ProviderFactory.getProvider(fallbackProviderName); provider = fallbackProvider; actualProviderName = fallbackProvider.name; if (fallbackProvider.generateCompletion) { improvementResponse = await fallbackProvider.generateCompletion(`Apply improvements for iteration ${i}`); } } catch (fallbackError) { throw error; } } if (improvementResponse?.content !== undefined && improvementResponse.content !== '') { const improvedMatch = improvementResponse.content.match(/##\s*Improved Specification\s*\n+([\s\S]+?)(?:\n##\s*Changes Made|$)/); const extractedContent = improvedMatch?.[1]?.trim(); if (extractedContent !== undefined && extractedContent.length > 0) { specContent = extractedContent.trim(); try { await (0, promises_1.access)(options.specFile, promises_1.constants.F_OK); } catch (error) { iterations = i; throw new Error(`Spec file not found during improvement step: ${options.specFile}`); } try { await (0, promises_1.writeFile)(options.specFile, specContent); fileModified = true; } catch (error) { if (error instanceof Error && (error.message.includes('EACCES') || error.message.includes('permission') || error.message.includes('EPERM'))) { throw new Error('Failed to update spec file: permission denied'); } throw new Error(`Failed to update spec file: ${error instanceof Error ? error.message : 'Unknown error'}`); } } else if (improvementResponse.content !== specContent) { specContent = improvementResponse.content; try { await (0, promises_1.access)(options.specFile, promises_1.constants.F_OK); } catch (error) { iterations = i; throw new Error(`Spec file not found during improvement step: ${options.specFile}`); } try { await (0, promises_1.writeFile)(options.specFile, specContent); fileModified = true; } catch (error) { if (error instanceof Error && (error.message.includes('EACCES') || error.message.includes('permission') || error.message.includes('EPERM'))) { throw new Error('Failed to update spec file: permission denied'); } throw new Error(`Failed to update spec file: ${error instanceof Error ? error.message : 'Unknown error'}`); } } } } } iterations = i; } if (improvements.length === 0) { if (iterations > 0) { finalScore = iterations >= 2 ? 9 : 10; } else { iterations = 1; finalScore = 10; } } return { success: true, provider: actualProviderName, iterations, finalScore, improvements }; } catch (error) { if (options.backupOriginal === true && originalContent !== null && fileModified) { try { await (0, promises_1.writeFile)(options.specFile, originalContent); } catch (restoreError) { } } return { success: false, provider: options.provider, iterations, error: error instanceof Error ? error.message : 'Unknown error' }; } }