153 lines
6.1 KiB
Plaintext
153 lines
6.1 KiB
Plaintext
diff --git a/tools/installer/lib/ide-setup.js b/tools/installer/lib/ide-setup.js
|
|
index a3882333..0845c91e 100644
|
|
--- a/tools/installer/lib/ide-setup.js
|
|
+++ b/tools/installer/lib/ide-setup.js
|
|
@@ -72,6 +72,9 @@ class IdeSetup extends BaseIdeSetup {
|
|
case 'kilo': {
|
|
return this.setupKilocode(installDir, selectedAgent);
|
|
}
|
|
+ case 'aicockpit': {
|
|
+ return this.setupAICockpit(installDir, selectedAgent);
|
|
+ }
|
|
case 'gemini': {
|
|
return this.setupGeminiCli(installDir, selectedAgent);
|
|
}
|
|
@@ -1921,6 +1924,137 @@ class IdeSetup extends BaseIdeSetup {
|
|
return true;
|
|
}
|
|
|
|
+ async setupAICockpit(installDir, selectedAgent) {
|
|
+ const ideConfig = await configLoader.getIdeConfiguration('aicockpit');
|
|
+ if (!ideConfig) {
|
|
+ console.log(chalk.red('✗ AI Cockpit configuration not found in install.config.yaml'));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|
|
+ const tasks = await this.getAllTaskIds(installDir);
|
|
+
|
|
+ // 1. Setup .aicockpitmodes file
|
|
+ const modesFilePath = path.join(installDir, ideConfig['modes-file']);
|
|
+ try {
|
|
+ let existingModes = [],
|
|
+ existingContent = '';
|
|
+ if (await fileManager.pathExists(modesFilePath)) {
|
|
+ existingContent = await fileManager.readFile(modesFilePath);
|
|
+ for (const match of existingContent.matchAll(/- slug: ([\w-]+)/g)) {
|
|
+ existingModes.push(match[1]);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ let newModesContent = '';
|
|
+
|
|
+ for (const agentId of agents) {
|
|
+ const slug = agentId.startsWith('bmad-') ? agentId : `bmad-${agentId}`;
|
|
+ if (existingModes.includes(slug)) {
|
|
+ console.log(chalk.dim(`Skipping ${agentId} - already exists in .aicockpitmodes`));
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ const agentPath = await this.findAgentPath(agentId, installDir);
|
|
+ if (!agentPath) {
|
|
+ console.log(chalk.red(`✗ Could not find agent file for ${agentId}`));
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ const agentContent = await fileManager.readFile(agentPath);
|
|
+ const yamlMatch = agentContent.match(/```ya?ml\r?\n([\s\S]*?)```/);
|
|
+ if (!yamlMatch) {
|
|
+ console.log(chalk.red(`✗ Could not extract YAML block for ${agentId}`));
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ const yamlContent = yamlMatch[1];
|
|
+ const parsedYaml = yaml.load(yamlContent);
|
|
+
|
|
+ const title = parsedYaml?.agent?.title || (await this.getAgentTitle(agentId, installDir));
|
|
+ const icon = parsedYaml?.agent?.icon || '🤖';
|
|
+ const roleDefinition = parsedYaml?.persona?.role || `You are a ${title}.`;
|
|
+
|
|
+ // The custom instructions are the entire agent file content.
|
|
+ const customInstructions = agentContent;
|
|
+
|
|
+ // Indent a string for YAML block scalar
|
|
+ const indent = (str) =>
|
|
+ str
|
|
+ .split('\n')
|
|
+ .map((s) => ` ${s}`)
|
|
+ .join('\n');
|
|
+
|
|
+ newModesContent += ` - slug: ${slug}\n`;
|
|
+ newModesContent += ` name: '${icon} ${title}'\n`;
|
|
+ newModesContent += ` roleDefinition: |\n`;
|
|
+ newModesContent += `${indent(roleDefinition)}\n`;
|
|
+ newModesContent += ` groups:\n`;
|
|
+ newModesContent += ` - read\n`;
|
|
+ newModesContent += ` - browser\n`;
|
|
+ newModesContent += ` - edit\n`;
|
|
+ newModesContent += ` - mcp\n`;
|
|
+ newModesContent += ` customInstructions: |\n`;
|
|
+ newModesContent += `${indent(customInstructions)}\n`;
|
|
+ }
|
|
+
|
|
+ const finalModesContent = existingContent
|
|
+ ? existingContent.trim() + '\n' + newModesContent
|
|
+ : 'customModes:\n' + newModesContent;
|
|
+
|
|
+ await fileManager.writeFile(modesFilePath, finalModesContent);
|
|
+ console.log(chalk.green(`✓ Created/updated ${ideConfig['modes-file']} file in project root`));
|
|
+ } catch (error) {
|
|
+ console.log(chalk.red(`✗ Failed to create ${ideConfig['modes-file']}:`, error.message));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // 2. Setup .aicockpit/rules/ directory
|
|
+ try {
|
|
+ const rulesDir = path.join(installDir, ideConfig['rules-dir']);
|
|
+ await fileManager.ensureDirectory(rulesDir);
|
|
+ for (const agentId of agents) {
|
|
+ const agentPath = await this.findAgentPath(agentId, installDir);
|
|
+ if (agentPath) {
|
|
+ const agentContent = await fileManager.readFile(agentPath);
|
|
+ const rulePath = path.join(rulesDir, `${agentId}.md`);
|
|
+ await fileManager.writeFile(rulePath, agentContent);
|
|
+ console.log(chalk.green(`✓ Created agent rule: ${agentId}.md`));
|
|
+ }
|
|
+ }
|
|
+ console.log(chalk.green(`✓ Created agent rules in ${ideConfig['rules-dir']}`));
|
|
+ } catch (error) {
|
|
+ console.log(chalk.red(`✗ Failed to create agent rules:`, error.message));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ // 3. Setup .aicockpit/workflows/ directory
|
|
+ try {
|
|
+ const workflowsDir = path.join(installDir, ideConfig['workflows-dir']);
|
|
+ await fileManager.ensureDirectory(workflowsDir);
|
|
+ for (const taskId of tasks) {
|
|
+ const taskPath = await this.findTaskPath(taskId, installDir);
|
|
+ if (taskPath) {
|
|
+ const taskContent = await fileManager.readFile(taskPath);
|
|
+ const workflowPath = path.join(workflowsDir, `${taskId}.md`);
|
|
+ await fileManager.writeFile(workflowPath, taskContent);
|
|
+ console.log(chalk.green(`✓ Created task workflow: ${taskId}.md`));
|
|
+ }
|
|
+ }
|
|
+ console.log(chalk.green(`✓ Created task workflows in ${ideConfig['workflows-dir']}`));
|
|
+ } catch (error) {
|
|
+ console.log(chalk.red(`✗ Failed to create task workflows:`, error.message));
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ console.log(chalk.green(`✓ AI Cockpit setup complete!`));
|
|
+ console.log(
|
|
+ chalk.dim('Custom modes, agent rules, and task workflows are now available in AI Cockpit'),
|
|
+ );
|
|
+
|
|
+ return true;
|
|
+ }
|
|
+
|
|
async setupCline(installDir, selectedAgent) {
|
|
const clineRulesDir = path.join(installDir, '.clinerules');
|
|
const agents = selectedAgent ? [selectedAgent] : await this.getAllAgentIds(installDir);
|