@jjdenhertog/ai-driven-development
Version:
AI-driven development workflow with learning capabilities for Claude
149 lines • 9.51 kB
JavaScript
;
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