@jjdenhertog/ai-driven-development
Version:
AI-driven development workflow with learning capabilities for Claude
165 lines • 9.09 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.executeTaskCommand = executeTaskCommand;
const fs_extra_1 = require("fs-extra");
const checkGitAuth_1 = require("../utils/git/checkGitAuth");
/* eslint-disable @typescript-eslint/restrict-template-expressions */
const claude_wrapper_1 = require("../../claude-wrapper");
const addHooks_1 = __importDefault(require("../utils/claude/addHooks"));
const removeHooks_1 = __importDefault(require("../utils/claude/removeHooks"));
const checkGitInitialized_1 = require("../utils/git/checkGitInitialized");
const createCommit_1 = require("../utils/git/createCommit");
const ensureBranch_1 = require("../utils/git/ensureBranch");
const ensureWorktree_1 = require("../utils/git/ensureWorktree");
const getGitInstance_1 = require("../utils/git/getGitInstance");
const isInWorktree_1 = require("../utils/git/isInWorktree");
const pullBranch_1 = require("../utils/git/pullBranch");
const pushBranch_1 = require("../utils/git/pushBranch");
const stageAllFiles_1 = require("../utils/git/stageAllFiles");
const logger_1 = require("../utils/logger");
const createSession_1 = require("../utils/storage/createSession");
const createSessionReport_1 = require("../utils/storage/createSessionReport");
const createTaskPR_1 = require("../utils/tasks/createTaskPR");
const getBranchName_1 = require("../utils/tasks/getBranchName");
const updateTaskFile_1 = require("../utils/tasks/updateTaskFile");
const validateTaskForExecution_1 = require("../utils/tasks/validateTaskForExecution");
function executeTaskCommand(options) {
return __awaiter(this, void 0, void 0, function* () {
const { taskId, dryRun, force, 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.');
const { logsDir, logPath } = (0, createSession_1.createSession)(taskId);
// Validate the task - expecting pending or in-progress status
const task = yield (0, validateTaskForExecution_1.validateTaskForExecution)({
taskId,
expectedStatuses: ['pending', 'in-progress'],
force,
refresh: true
});
///////////////////////////////////////////////////////////
// Goal:
// 1. Ensure the branch for the task exists
// 2. Ensure the worktree for the task exists
// 3. Ensure the worktree branh is pulled
///////////////////////////////////////////////////////////
(0, logger_1.log)(`Preparing git branch...`, 'success', undefined, logPath);
const branchName = (0, getBranchName_1.getBranchName)(task);
yield (0, ensureBranch_1.ensureBranch)(branchName);
const worktreeFolder = branchName.split('/').at(-1) || branchName;
const worktreePath = `.aidev-${worktreeFolder}`;
yield (0, ensureWorktree_1.ensureWorktree)(branchName, worktreePath);
yield (0, pullBranch_1.pullBranch)(branchName, worktreePath);
(0, logger_1.log)(`Executing Task: ${task.id} - ${task.name}`, 'info', undefined, logPath);
if (dryRun) {
(0, logger_1.log)('Dry Run Mode - No changes will be made', 'warn', undefined, logPath);
(0, logger_1.log)(` Task File: ${task.path}`, 'info', undefined, logPath);
(0, logger_1.log)(` Branch Name: ${(0, getBranchName_1.getBranchName)(task)}`, 'info', undefined, logPath);
return;
}
// Create session
(0, logger_1.log)(`Starting execution of task ${task.id}`, 'info', undefined, logPath);
// Update task file with execution metadata
(0, updateTaskFile_1.updateTaskFile)(task.path, {
branch: branchName,
started_at: new Date().toISOString()
});
// Step 3: Execute Claude
(0, logger_1.log)('Starting Claude with aidev-code-task command...', 'success', undefined, logPath);
const args = [];
if (dangerouslySkipPermission)
args.push('--dangerously-skip-permissions');
// Add hooks for claude
(0, addHooks_1.default)(worktreePath);
// Execute Claude and wait for completion
const result = yield (0, claude_wrapper_1.executeClaudeCommand)({
cwd: worktreePath,
command: `/aidev-code-task ${task.id}-${task.name}`,
args,
});
// We no longer capture output - hooks will handle logging
(0, logger_1.log)(`\nClaude command exited with code: ${result.exitCode}`, 'info', undefined, logPath);
// Create session report from debug logs and transcript
(0, logger_1.log)('Creating session report...', 'info', undefined, logPath);
const sessionReport = yield (0, createSessionReport_1.createSessionReport)({
taskId: task.id,
taskName: task.name,
worktreePath,
logsDir,
exitCode: result.exitCode
});
// Remove hooks for claude
(0, removeHooks_1.default)(worktreePath);
if (!sessionReport.success) {
(0, logger_1.log)(`Claude command failed`, 'error', undefined, logPath);
(0, updateTaskFile_1.updateTaskFile)(task.path, {
status: 'failed'
});
(0, logger_1.log)(`Removing worktree...`, 'info', undefined, logPath);
const git = (0, getGitInstance_1.getGitInstance)();
try {
yield git.raw(['worktree', 'remove', '--force', worktreePath]);
}
catch (_error) {
(0, fs_extra_1.rmSync)(worktreePath, { force: true, recursive: true });
}
yield git.raw(['branch', '-D', branchName, '--force']);
return;
}
///////////////////////////////////////////////////////////
// Update task status and create PR
///////////////////////////////////////////////////////////
try {
(0, logger_1.log)(`Claude command success...`, 'success', undefined, logPath);
// Then immediately to completed for PR creation
(0, updateTaskFile_1.updateTaskFile)(task.path, {
status: 'completed'
});
(0, logger_1.log)(`Committing and pushing changes...`, 'info', undefined, logPath);
yield (0, stageAllFiles_1.stageAllFiles)(worktreePath);
yield (0, createCommit_1.createCommit)(`complete task ${task.id} - ${task.name} (AI-generated)`, {
prefix: 'feat',
cwd: worktreePath
});
const pushResult = yield (0, pushBranch_1.pushBranch)(branchName, worktreePath);
if (!pushResult.success)
(0, logger_1.log)(`Failed to push changes to remote: ${pushResult.error}`, 'error', undefined, logPath);
// Create PR
if ((0, checkGitAuth_1.checkGitAuth)()) {
(0, logger_1.log)(`Creating PR...`, 'info', undefined, logPath);
yield (0, createTaskPR_1.createTaskPR)(task, branchName, worktreePath);
}
///////////////////////////////////////////////////////////
// Remove work tree
///////////////////////////////////////////////////////////
(0, logger_1.log)(`Removing worktree...`, 'info', undefined, logPath);
const git = (0, getGitInstance_1.getGitInstance)();
try {
yield git.raw(['worktree', 'remove', '--force', worktreePath]);
}
catch (_error) {
(0, fs_extra_1.rmSync)(worktreePath, { force: true, recursive: true });
}
yield git.raw(['branch', '-D', branchName, '--force']);
}
catch (error) {
(0, logger_1.log)(`Failed to finish task ${task.id} - ${task.name}: ${error instanceof Error ? error.message : 'Unknown error'}`, 'error');
}
});
}
//# sourceMappingURL=executeTaskCommand.js.map