@bestdefense/bd-agent
Version:
An AI-powered coding assistant CLI that connects to AWS Bedrock
142 lines (138 loc) • 5.85 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.SlashCommandManager = void 0;
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const chalk_1 = __importDefault(require("chalk"));
class SlashCommandManager {
commands = new Map();
commandsDir;
constructor() {
// Default commands directory in user's home
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
this.commandsDir = path_1.default.join(homeDir, '.bd-agent', 'commands');
this.ensureCommandsDirectory();
this.loadCommands();
this.loadBuiltInCommands();
}
ensureCommandsDirectory() {
if (!fs_1.default.existsSync(this.commandsDir)) {
fs_1.default.mkdirSync(this.commandsDir, { recursive: true });
// Create example command
const examplePath = path_1.default.join(this.commandsDir, 'example.md');
if (!fs_1.default.existsSync(examplePath)) {
fs_1.default.writeFileSync(examplePath, `# Example Command
This is an example slash command. You can create your own by adding markdown files to:
${this.commandsDir}
## Usage
\`/example [optional argument]\`
## Prompt
Please provide a helpful example of {{ARG1:what you want an example of}}.
`);
}
}
}
loadBuiltInCommands() {
// Add built-in commands
this.commands.set('compact', {
name: 'compact',
description: 'Generate compact, minimal code without comments',
content: 'Please provide a compact, minimal implementation without any comments or unnecessary whitespace. Focus on brevity and efficiency.',
arguments: []
});
this.commands.set('explain', {
name: 'explain',
description: 'Explain code or concepts in detail',
content: 'Please provide a detailed explanation of {{ARG1:the code or concept}}, including how it works, why it\'s used, and any important considerations.',
arguments: ['topic']
});
this.commands.set('review', {
name: 'review',
description: 'Review code for improvements',
content: `Please review the following code and provide feedback on:
1. Code quality and readability
2. Potential bugs or issues
3. Performance considerations
4. Best practices
5. Suggested improvements
Code to review: {{ARG1:paste or describe the code}}`,
arguments: ['code']
});
this.commands.set('test', {
name: 'test',
description: 'Generate tests for code',
content: 'Please generate comprehensive tests for {{ARG1:the code or functionality}}, including edge cases and error scenarios.',
arguments: ['code']
});
}
loadCommands() {
if (!fs_1.default.existsSync(this.commandsDir))
return;
const files = fs_1.default.readdirSync(this.commandsDir).filter(f => f.endsWith('.md'));
for (const file of files) {
try {
const filePath = path_1.default.join(this.commandsDir, file);
const content = fs_1.default.readFileSync(filePath, 'utf-8');
const name = path_1.default.basename(file, '.md').toLowerCase();
// Parse the markdown to extract description
const lines = content.split('\n');
const titleLine = lines.find(l => l.startsWith('# '));
const description = titleLine ? titleLine.replace('# ', '').trim() : name;
// Extract arguments from content (looking for {{ARG1:description}} patterns)
const argPattern = /\{\{ARG(\d+):([^}]+)\}\}/g;
const matches = [...content.matchAll(argPattern)];
const commandArgs = matches.map(m => m[2].split(':')[0].trim());
this.commands.set(name, {
name,
description,
content,
arguments: commandArgs
});
}
catch (error) {
console.error(chalk_1.default.yellow(`Warning: Failed to load command ${file}:`, error));
}
}
}
getCommand(name) {
return this.commands.get(name.toLowerCase());
}
getAllCommands() {
return Array.from(this.commands.values()).sort((a, b) => a.name.localeCompare(b.name));
}
executeCommand(commandName, args) {
const command = this.getCommand(commandName);
if (!command)
return null;
let content = command.content;
// Replace argument placeholders
const argPattern = /\{\{ARG(\d+):([^}]+)\}\}/g;
content = content.replace(argPattern, (match, index, description) => {
const argIndex = parseInt(index) - 1;
return args[argIndex] || description.split(':').pop()?.trim() || '';
});
return content;
}
createCommand(name, content) {
const filePath = path_1.default.join(this.commandsDir, `${name}.md`);
fs_1.default.writeFileSync(filePath, content);
this.loadCommands(); // Reload commands
}
deleteCommand(name) {
const filePath = path_1.default.join(this.commandsDir, `${name}.md`);
if (fs_1.default.existsSync(filePath)) {
fs_1.default.unlinkSync(filePath);
this.commands.delete(name);
return true;
}
return false;
}
getCommandsDirectory() {
return this.commandsDir;
}
}
exports.SlashCommandManager = SlashCommandManager;
//# sourceMappingURL=slash-commands.js.map