UNPKG

@jjdenhertog/ai-driven-development

Version:

AI-driven development workflow with learning capabilities for Claude

149 lines 9.51 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.learningCommand = learningCommand; const claude_wrapper_1 = require("../../claude-wrapper"); const config_1 = require("../config"); const addHooks_1 = __importDefault(require("../utils/claude/addHooks")); /* eslint-disable max-depth */ const autoRetryClaude_1 = require("../utils/claude/autoRetryClaude"); const removeHooks_1 = __importDefault(require("../utils/claude/removeHooks")); const checkBranchMerged_1 = require("../utils/git/checkBranchMerged"); const checkGitInitialized_1 = require("../utils/git/checkGitInitialized"); const getCommits_1 = require("../utils/git/getCommits"); const isInWorktree_1 = require("../utils/git/isInWorktree"); const logger_1 = require("../utils/logger"); const sleep_1 = require("../utils/sleep"); const createSession_1 = require("../utils/storage/createSession"); const createSessionReport_1 = require("../utils/storage/createSessionReport"); const saveUserChanges_1 = require("../utils/storage/saveUserChanges"); const getTasks_1 = require("../utils/tasks/getTasks"); const updateTaskFile_1 = require("../utils/tasks/updateTaskFile"); function learningCommand(options) { return __awaiter(this, void 0, void 0, function* () { const { dangerouslySkipPermission } = options; // Ensure git auth if (!(yield (0, checkGitInitialized_1.checkGitInitialized)())) throw new Error('Git is not initialized. Please run `git init` in the root of the repository.'); // Check if we are in a worktree if (yield (0, isInWorktree_1.isInWorktree)()) throw new Error('This command must be run from the root of the repository.'); // Switch to main branch (0, logger_1.log)('Learning command started. Monitoring for completed tasks...', 'success'); if (dangerouslySkipPermission) (0, logger_1.log)('Dangerously skipping permission checks of Claude Code', 'warn'); const allTasks = yield (0, getTasks_1.getTasks)(); let tasks = allTasks.filter(task => task.status != 'archived'); const mainBranch = config_1.MAIN_BRANCH; try { // eslint-disable-next-line no-constant-condition while (true) { // Reload the tasks const refreshedTasks = yield (0, getTasks_1.getTasks)(); tasks = refreshedTasks.filter(task => task.status != 'archived'); // Check for completed tasks const completedTasks = tasks.filter(task => task.status === 'completed'); if (completedTasks.length > 0) { (0, logger_1.log)(`Found ${completedTasks.length} completed tasks to process`, 'info'); // Process each completed task sequentially for (const task of completedTasks) { try { // Check if the task branch has been merged into main branch if (!task.branch) { (0, logger_1.log)(`Task ${task.id} has no branch associated. Skipping...`, 'warn'); continue; } const isMerged = yield (0, checkBranchMerged_1.checkBranchMerged)(task.branch, mainBranch); if (!isMerged) { (0, logger_1.log)(`Task ${task.id} branch '${task.branch}' is not merged into ${mainBranch}. Skipping...`, 'info'); continue; } // Branch is merged, now get the commits (0, logger_1.log)(`Task ${task.id} branch '${task.branch}' is merged. Processing commits...`, 'info'); const commits = yield (0, getCommits_1.getCommits)(task.branch); if (!commits || commits.length === 0) { (0, logger_1.log)(`No commits found for task ${task.id}`, 'warn'); continue; } const userCommits = commits.filter(commit => !commit.isAI); const aiCommits = commits.filter(commit => commit.isAI); (0, logger_1.log)(`Found ${commits.length} commits (${userCommits.length} user, ${aiCommits.length} AI) for task ${task.id}`, 'info'); if (userCommits.length > 0) { (0, saveUserChanges_1.saveUserChanges)(task.id, userCommits); const worktreePath = process.cwd(); const { logsDir, logPath } = (0, createSession_1.createSession)(task.id); (0, logger_1.log)(`Processing ${userCommits.length} user commits for learning...`, 'info', undefined, logPath); // Add hooks for claude command (0, addHooks_1.default)(worktreePath); try { const claudeCommand = () => __awaiter(this, void 0, void 0, function* () { const args = []; if (dangerouslySkipPermission) args.push('--dangerously-skip-permissions'); const result = yield (0, claude_wrapper_1.executeClaudeCommand)({ cwd: worktreePath, command: `Please complete the following steps IN ORDER: 1. First, use the Read tool to read the entire contents of the file: .aidev-storage/prompts/aidev-learn.md 2. After reading the file, list the key constraints and outputs for this phase. 3. Then execute the instructions from that file with these parameters: {"task_filename": "${task.id}-${task.name}" } 4. Show me progress as you work through the phase. `, args, }); const sessionReport = yield (0, createSessionReport_1.createSessionReport)({ taskId: task.id, taskName: task.name, worktreePath, logsDir, exitCode: result.exitCode, fileName: 'aidev-learn' }); return sessionReport; }); // Run Claude with retry logic for usage limits yield (0, autoRetryClaude_1.autoRetryClaude)({ claudeCommand, logPath }); (0, updateTaskFile_1.updateTaskFile)(task.path, { status: 'archived' }); } catch (_e) { (0, logger_1.log)(`Error processing task ${task.id}: ${String(_e)}`, 'error', undefined, logPath); } (0, removeHooks_1.default)(worktreePath); } else { (0, logger_1.log)(`No user commits found for task ${task.id}. Archiving...`, 'info'); (0, updateTaskFile_1.updateTaskFile)(task.path, { status: 'archived' }); } // await processCompletedTask(task, dangerouslySkipPermission); } catch (error) { (0, logger_1.log)(`Error processing task ${task.id}: ${String(error)}`, 'error'); } } } // Sleep for 30 seconds before next check (0, logger_1.log)("Sleeping for 300 seconds, waiting for next iteration", 'info'); yield (0, sleep_1.sleep)(300000); } } catch (error) { (0, logger_1.log)(`Learning command error: ${String(error)}`, 'error'); throw error; } }); } //# sourceMappingURL=learningCommand.js.map