refactor(ide): delegate detection to handlers (#680)

This commit is contained in:
Alex Verkhovsky
2025-10-05 20:13:11 -07:00
committed by GitHub
parent c9ffe202d5
commit b999dd1315
4 changed files with 54 additions and 33 deletions

View File

@@ -15,6 +15,8 @@ class BaseIdeSetup {
this.preferred = preferred; // Whether this IDE should be shown in preferred list
this.configDir = null; // Override in subclasses
this.rulesDir = null; // Override in subclasses
this.configFile = null; // Override in subclasses when detection is file-based
this.detectionPaths = []; // Additional paths that indicate the IDE is configured
this.xmlHandler = new XmlHandler();
}
@@ -46,6 +48,40 @@ class BaseIdeSetup {
}
}
/**
* Detect whether this IDE already has configuration in the project
* Subclasses can override for custom logic
* @param {string} projectDir - Project directory
* @returns {boolean}
*/
async detect(projectDir) {
const pathsToCheck = [];
if (this.configDir) {
pathsToCheck.push(path.join(projectDir, this.configDir));
}
if (this.configFile) {
pathsToCheck.push(path.join(projectDir, this.configFile));
}
if (Array.isArray(this.detectionPaths)) {
for (const candidate of this.detectionPaths) {
if (!candidate) continue;
const resolved = path.isAbsolute(candidate) ? candidate : path.join(projectDir, candidate);
pathsToCheck.push(resolved);
}
}
for (const candidate of pathsToCheck) {
if (await fs.pathExists(candidate)) {
return true;
}
}
return false;
}
/**
* Get list of agents from BMAD installation
* @param {string} bmadDir - BMAD installation directory

View File

@@ -16,6 +16,7 @@ class AuggieSetup extends BaseIdeSetup {
{ name: 'User Home (~/.auggie/commands)', value: path.join(os.homedir(), '.auggie', 'commands') },
{ name: 'Custom Location', value: 'custom' },
];
this.detectionPaths = ['.auggie'];
}
/**

View File

@@ -80,6 +80,20 @@ class CodexSetup extends BaseIdeSetup {
};
}
/**
* Detect Codex installation by checking for BMAD prompt exports
*/
async detect(_projectDir) {
const destDir = this.getCodexPromptDir();
if (!(await fs.pathExists(destDir))) {
return false;
}
const entries = await fs.readdir(destDir);
return entries.some((entry) => entry.startsWith('bmad-'));
}
/**
* Collect Claude-style artifacts for Codex export.
* Returns the normalized artifact list for further processing.

View File

@@ -1,7 +1,6 @@
const fs = require('fs-extra');
const path = require('node:path');
const chalk = require('chalk');
const os = require('node:os');
/**
* IDE Manager - handles IDE-specific setup
@@ -166,38 +165,9 @@ class IdeManager {
async detectInstalledIdes(projectDir) {
const detected = [];
// Check for IDE-specific directories
const ideChecks = {
cursor: '.cursor',
'claude-code': '.claude',
windsurf: '.windsurf',
cline: '.clinerules',
roo: '.roomodes',
trae: '.trae',
kilo: '.kilocodemodes',
gemini: '.gemini',
qwen: '.qwen',
crush: '.crush',
iflow: '.iflow',
auggie: '.auggie',
'github-copilot': '.github/chatmodes',
vscode: '.vscode',
idea: '.idea',
};
for (const [ide, dir] of Object.entries(ideChecks)) {
const idePath = path.join(projectDir, dir);
if (await fs.pathExists(idePath)) {
detected.push(ide);
}
}
// Check Codex prompt directory for BMAD exports
const codexPromptDir = path.join(os.homedir(), '.codex', 'prompts');
if (await fs.pathExists(codexPromptDir)) {
const codexEntries = await fs.readdir(codexPromptDir);
if (codexEntries.some((file) => file.startsWith('bmad-'))) {
detected.push('codex');
for (const [name, handler] of this.handlers) {
if (typeof handler.detect === 'function' && (await handler.detect(projectDir))) {
detected.push(name);
}
}