fix: address CodeRabbit PR review comments for Bob IDE support
- Remove leftover '// Made with Bob' debug comment - Guard artifact.sourcePath before calling path.relative() to prevent TypeError - Fix run-on customInstructions string with proper punctuation in createModeObject - Move fs-extra require to top of file; remove inline requires from clearBmadWorkflows/cleanup - Wrap write sequence in try/catch with rollback to prevent partial state on failure - Use metadata.title and metadata.icon in installCustomAgentLauncher instead of ignoring param - Align installCustomAgentLauncher mode object with createModeObject (icon in name, fixed instructions) - Remove unused .bobmodes entry from .gitignore (.bob already covers the directory) - Sync bob description in tools/cli/installers/lib/ide/platform-codes.yaml to match tools/platform-codes.yaml
This commit is contained in:
parent
d21ed92ae8
commit
9bfcf6e0a3
|
|
@ -54,7 +54,6 @@ _bmad-output
|
||||||
.opencode
|
.opencode
|
||||||
.qwen
|
.qwen
|
||||||
.rovodev
|
.rovodev
|
||||||
.bobmodes
|
|
||||||
.bob
|
.bob
|
||||||
.kilocodemodes
|
.kilocodemodes
|
||||||
.claude/commands
|
.claude/commands
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
const path = require('node:path');
|
const path = require('node:path');
|
||||||
|
const fs = require('fs-extra');
|
||||||
const { BaseIdeSetup } = require('./_base-ide');
|
const { BaseIdeSetup } = require('./_base-ide');
|
||||||
const yaml = require('yaml');
|
const yaml = require('yaml');
|
||||||
const prompts = require('../../../lib/prompts');
|
const prompts = require('../../../lib/prompts');
|
||||||
|
|
@ -64,6 +65,13 @@ class BobSetup extends BaseIdeSetup {
|
||||||
|
|
||||||
// Write .bob/custom_modes.yaml file with proper YAML structure
|
// Write .bob/custom_modes.yaml file with proper YAML structure
|
||||||
const finalContent = yaml.stringify(config, { lineWidth: 0 });
|
const finalContent = yaml.stringify(config, { lineWidth: 0 });
|
||||||
|
const workflowsDir = path.join(projectDir, '.bob', 'workflows');
|
||||||
|
|
||||||
|
let workflowCount = 0;
|
||||||
|
let taskCount = 0;
|
||||||
|
let toolCount = 0;
|
||||||
|
|
||||||
|
try {
|
||||||
await this.writeFile(bobModesPath, finalContent);
|
await this.writeFile(bobModesPath, finalContent);
|
||||||
|
|
||||||
// Generate workflow commands
|
// Generate workflow commands
|
||||||
|
|
@ -71,14 +79,13 @@ class BobSetup extends BaseIdeSetup {
|
||||||
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
|
const { artifacts: workflowArtifacts } = await workflowGenerator.collectWorkflowArtifacts(bmadDir);
|
||||||
|
|
||||||
// Write to .bob/workflows/ directory
|
// Write to .bob/workflows/ directory
|
||||||
const workflowsDir = path.join(projectDir, '.bob', 'workflows');
|
|
||||||
await this.ensureDir(workflowsDir);
|
await this.ensureDir(workflowsDir);
|
||||||
|
|
||||||
// Clear old BMAD workflows before writing new ones
|
// Clear old BMAD workflows before writing new ones
|
||||||
await this.clearBmadWorkflows(workflowsDir);
|
await this.clearBmadWorkflows(workflowsDir);
|
||||||
|
|
||||||
// Write workflow files
|
// Write workflow files
|
||||||
const workflowCount = await workflowGenerator.writeDashArtifacts(workflowsDir, workflowArtifacts);
|
workflowCount = await workflowGenerator.writeDashArtifacts(workflowsDir, workflowArtifacts);
|
||||||
|
|
||||||
// Generate task and tool commands
|
// Generate task and tool commands
|
||||||
const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName);
|
const taskToolGen = new TaskToolCommandGenerator(this.bmadFolderName);
|
||||||
|
|
@ -86,8 +93,18 @@ class BobSetup extends BaseIdeSetup {
|
||||||
|
|
||||||
// Write task/tool files to workflows directory (same location as workflows)
|
// Write task/tool files to workflows directory (same location as workflows)
|
||||||
await taskToolGen.writeDashArtifacts(workflowsDir, taskToolArtifacts);
|
await taskToolGen.writeDashArtifacts(workflowsDir, taskToolArtifacts);
|
||||||
const taskCount = taskToolCounts.tasks || 0;
|
taskCount = taskToolCounts.tasks || 0;
|
||||||
const toolCount = taskToolCounts.tools || 0;
|
toolCount = taskToolCounts.tools || 0;
|
||||||
|
} catch (error) {
|
||||||
|
// Roll back partial writes to avoid inconsistent state
|
||||||
|
try {
|
||||||
|
await fs.remove(bobModesPath);
|
||||||
|
} catch {
|
||||||
|
// Ignore cleanup errors
|
||||||
|
}
|
||||||
|
await this.clearBmadWorkflows(workflowsDir);
|
||||||
|
throw new Error(`Failed to write Bob configuration: ${error.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
if (!options.silent) {
|
if (!options.silent) {
|
||||||
await prompts.log.success(
|
await prompts.log.success(
|
||||||
|
|
@ -131,8 +148,10 @@ class BobSetup extends BaseIdeSetup {
|
||||||
|
|
||||||
const roleDefinition = `You are a ${title} specializing in ${title.toLowerCase()} tasks.`;
|
const roleDefinition = `You are a ${title} specializing in ${title.toLowerCase()} tasks.`;
|
||||||
|
|
||||||
// Get relative path
|
// Get relative path (fall back to artifact name if sourcePath unavailable)
|
||||||
const relativePath = path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/');
|
const relativePath = artifact.sourcePath
|
||||||
|
? path.relative(projectDir, artifact.sourcePath).replaceAll('\\', '/')
|
||||||
|
: `${this.bmadFolderName}/agents/${artifact.name}.md`;
|
||||||
|
|
||||||
// Build mode object (Bob uses same schema as Kilo/Roo)
|
// Build mode object (Bob uses same schema as Kilo/Roo)
|
||||||
return {
|
return {
|
||||||
|
|
@ -140,7 +159,7 @@ class BobSetup extends BaseIdeSetup {
|
||||||
name: `${icon} ${title}`,
|
name: `${icon} ${title}`,
|
||||||
roleDefinition: roleDefinition,
|
roleDefinition: roleDefinition,
|
||||||
whenToUse: whenToUse,
|
whenToUse: whenToUse,
|
||||||
customInstructions: `${activationHeader} Read the full YAML from ${relativePath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
|
customInstructions: `${activationHeader} Read the full agent definition from ${relativePath}. Start activation to assume this persona. Follow the startup section instructions. Stay in this mode until told to exit.\n`,
|
||||||
groups: ['read', 'edit', 'browser', 'command', 'mcp'],
|
groups: ['read', 'edit', 'browser', 'command', 'mcp'],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -160,8 +179,7 @@ class BobSetup extends BaseIdeSetup {
|
||||||
* @param {string} workflowsDir - Workflows directory path
|
* @param {string} workflowsDir - Workflows directory path
|
||||||
*/
|
*/
|
||||||
async clearBmadWorkflows(workflowsDir) {
|
async clearBmadWorkflows(workflowsDir) {
|
||||||
const fs = require('fs-extra');
|
if (!(await this.pathExists(workflowsDir))) return;
|
||||||
if (!(await fs.pathExists(workflowsDir))) return;
|
|
||||||
|
|
||||||
const entries = await fs.readdir(workflowsDir);
|
const entries = await fs.readdir(workflowsDir);
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
|
|
@ -175,11 +193,10 @@ class BobSetup extends BaseIdeSetup {
|
||||||
* Cleanup IBM Bob configuration
|
* Cleanup IBM Bob configuration
|
||||||
*/
|
*/
|
||||||
async cleanup(projectDir, options = {}) {
|
async cleanup(projectDir, options = {}) {
|
||||||
const fs = require('fs-extra');
|
|
||||||
const bobModesPath = path.join(projectDir, this.configFile);
|
const bobModesPath = path.join(projectDir, this.configFile);
|
||||||
|
|
||||||
if (await fs.pathExists(bobModesPath)) {
|
if (await this.pathExists(bobModesPath)) {
|
||||||
const content = await fs.readFile(bobModesPath, 'utf8');
|
const content = await this.readFile(bobModesPath);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const config = yaml.parse(content) || {};
|
const config = yaml.parse(content) || {};
|
||||||
|
|
@ -191,7 +208,7 @@ class BobSetup extends BaseIdeSetup {
|
||||||
const removedCount = originalCount - config.customModes.length;
|
const removedCount = originalCount - config.customModes.length;
|
||||||
|
|
||||||
if (removedCount > 0) {
|
if (removedCount > 0) {
|
||||||
await fs.writeFile(bobModesPath, yaml.stringify(config, { lineWidth: 0 }));
|
await this.writeFile(bobModesPath, yaml.stringify(config, { lineWidth: 0 }));
|
||||||
if (!options.silent) await prompts.log.message(`Removed ${removedCount} BMAD modes from .bob/custom_modes.yaml`);
|
if (!options.silent) await prompts.log.message(`Removed ${removedCount} BMAD modes from .bob/custom_modes.yaml`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -248,14 +265,15 @@ class BobSetup extends BaseIdeSetup {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add custom mode object
|
// Add custom mode object
|
||||||
const title = `BMAD Custom: ${agentName}`;
|
const title = metadata?.title || `BMAD Custom: ${agentName}`;
|
||||||
|
const icon = metadata?.icon || '🤖';
|
||||||
const activationHeader = (await this.getAgentCommandHeader()).trim();
|
const activationHeader = (await this.getAgentCommandHeader()).trim();
|
||||||
config.customModes.push({
|
config.customModes.push({
|
||||||
slug: slug,
|
slug: slug,
|
||||||
name: title,
|
name: `${icon} ${title}`,
|
||||||
roleDefinition: `You are a custom BMAD agent "${agentName}". Follow the persona and instructions from the agent file.`,
|
roleDefinition: `You are a custom BMAD agent "${agentName}". Follow the persona and instructions from the agent file.`,
|
||||||
whenToUse: `Use for custom BMAD agent "${agentName}" tasks`,
|
whenToUse: `Use for custom BMAD agent "${agentName}" tasks`,
|
||||||
customInstructions: `${activationHeader} Read the full agent from ${agentPath} start activation to alter your state of being follow startup section instructions stay in this being until told to exit this mode\n`,
|
customInstructions: `${activationHeader} Read the full agent definition from ${agentPath}. Start activation to assume this persona. Follow the startup section instructions. Stay in this mode until told to exit.\n`,
|
||||||
groups: ['read', 'edit', 'browser', 'command', 'mcp'],
|
groups: ['read', 'edit', 'browser', 'command', 'mcp'],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ platforms:
|
||||||
name: "IBM Bob"
|
name: "IBM Bob"
|
||||||
preferred: false
|
preferred: false
|
||||||
category: ide
|
category: ide
|
||||||
description: "IBM's AI development environment"
|
description: "IBM's agentic IDE for AI-powered development"
|
||||||
# No installer config - uses custom bob.js (creates .bob/custom_modes.yaml)
|
# No installer config - uses custom bob.js (creates .bob/custom_modes.yaml)
|
||||||
|
|
||||||
claude-code:
|
claude-code:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue