autoagent-cli
Version:
Run autonomous AI agents using Claude or Gemini for task execution
166 lines (165 loc) • 5.93 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.HookManager = void 0;
const child_process_1 = require("child_process");
const git_commit_hook_js_1 = require("../hooks/git-commit-hook.js");
const git_push_hook_js_1 = require("../hooks/git-push-hook.js");
class HookManager {
constructor(config, sessionId, workspace) {
this.config = config;
this.sessionId = sessionId;
this.workspace = workspace;
}
async executeHooks(hookPoint, data) {
const hooks = this.config[hookPoint] || [];
const hookData = {
...data,
eventName: hookPoint,
sessionId: this.sessionId,
workspace: this.workspace,
timestamp: Date.now()
};
for (const hook of hooks) {
try {
let result;
if (hook.type === 'command') {
result = await this.executeCommandHook(hook, hookData, hookPoint);
}
else {
result = await this.executeBuiltinHook(hook, hookData);
}
if (result.blocked) {
return result;
}
if (result.output !== undefined && result.output !== null && result.output.length > 0) {
console.log(result.output);
}
}
catch (error) {
console.error(`Hook error: ${error instanceof Error ? error.message : String(error)}`);
}
}
return { blocked: false };
}
async executeCommandHook(hook, data, hookPoint) {
if (hook.command === undefined || hook.command === null || hook.command === '') {
throw new Error('Command hook missing command field');
}
const command = this.interpolateCommand(hook.command, data);
const input = JSON.stringify(data, null, 2);
const timeout = hook.timeout ?? 60000;
const result = await this.runCommand(command, input, timeout);
if (result.stdout && result.stdout.length > 0) {
console.log(result.stdout);
}
if (result.exitCode === 2 && (hookPoint.startsWith('Pre') || hookPoint === 'Stop')) {
return {
blocked: true,
reason: result.stderr || 'Blocked by hook',
output: result.stdout
};
}
else if (result.exitCode !== 0) {
if (result.stderr && result.stderr.length > 0) {
console.error(result.stderr);
}
}
if (result.stdout && result.stdout.length > 0) {
try {
const jsonOutput = JSON.parse(result.stdout);
if (jsonOutput.decision === 'block') {
return {
blocked: true,
reason: jsonOutput.reason ?? 'Blocked by hook',
output: jsonOutput.feedback
};
}
}
catch {
}
}
return {
blocked: false,
output: result.stdout
};
}
async executeBuiltinHook(hook, data) {
switch (hook.type) {
case 'git-commit': {
const gitCommitHook = new git_commit_hook_js_1.GitCommitHook();
return gitCommitHook.execute(data, hook);
}
case 'git-push': {
const gitPushHook = new git_push_hook_js_1.GitPushHook();
return gitPushHook.execute(data, hook);
}
default: {
console.warn(`Built-in hook type '${hook.type}' not yet implemented`);
return { blocked: false };
}
}
}
interpolateCommand(command, data) {
return command.replace(/\{\{(\w+)\}\}/g, (match, key) => {
const value = data[key];
if (value === undefined) {
return match;
}
if (Array.isArray(value)) {
return value.join(' ');
}
return String(value);
});
}
async runCommand(command, input, timeout) {
return new Promise((resolve) => {
let stdout = '';
let stderr = '';
let timedOut = false;
const child = (0, child_process_1.spawn)(command, {
shell: true,
cwd: this.workspace,
env: { ...process.env },
windowsHide: true
});
const timer = setTimeout(() => {
timedOut = true;
child.kill('SIGTERM');
setTimeout(() => {
if (!child.killed) {
child.kill('SIGKILL');
}
}, 5000);
}, timeout);
child.stdout?.on('data', (data) => {
stdout += data.toString();
});
child.stderr?.on('data', (data) => {
stderr += data.toString();
});
if (input.length > 0) {
child.stdin?.write(input);
child.stdin?.end();
}
child.on('exit', (code, signal) => {
clearTimeout(timer);
resolve({
exitCode: code ?? (signal ? 1 : 0),
stdout: stdout.trim(),
stderr: stderr.trim(),
timedOut
});
});
child.on('error', (error) => {
clearTimeout(timer);
resolve({
exitCode: 1,
stdout: stdout.trim(),
stderr: `Failed to execute command: ${error.message}`,
timedOut: false
});
});
});
}
}
exports.HookManager = HookManager;