create-byan-agent 2.7.1 → 2.7.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Claude Code Platform Support
3
+ *
4
+ * Detects and installs MCP server config for Claude Code.
5
+ * Uses agent Claude for native integration via MCP protocol.
6
+ *
7
+ * @module platforms/claude-code
8
+ */
9
+
10
+ const path = require('path');
11
+ const os = require('os');
12
+ const fileUtils = require('../utils/file-utils');
13
+ const logger = require('../utils/logger');
14
+
15
+ const PLATFORM_NAME = 'Claude Code';
16
+ const MCP_SERVER_FILENAME = 'byan-mcp-server.js';
17
+
18
+ /**
19
+ * Get config path for current platform
20
+ *
21
+ * @returns {string|null}
22
+ */
23
+ function getConfigPath() {
24
+ const platform = os.platform();
25
+ const home = os.homedir();
26
+
27
+ switch (platform) {
28
+ case 'darwin':
29
+ return path.join(home, 'Library/Application Support/Claude/claude_desktop_config.json');
30
+ case 'win32':
31
+ return path.join(home, 'AppData/Roaming/Claude/claude_desktop_config.json');
32
+ case 'linux':
33
+ return path.join(home, '.config/Claude/claude_desktop_config.json');
34
+ default:
35
+ return null;
36
+ }
37
+ }
38
+
39
+ /**
40
+ * Detect if Claude Code is installed
41
+ *
42
+ * @returns {Promise<boolean>}
43
+ */
44
+ async function detect() {
45
+ const configPath = getConfigPath();
46
+ if (!configPath) return false;
47
+
48
+ return fileUtils.exists(configPath);
49
+ }
50
+
51
+ /**
52
+ * Install MCP server config for Claude Code
53
+ *
54
+ * Delegates to agent Claude for native integration.
55
+ * Falls back to basic JSON update if agent unavailable.
56
+ *
57
+ * @param {string} projectRoot - Project root directory
58
+ * @param {string[]} agents - Agent names to install
59
+ * @param {Object} config - Installation config
60
+ * @param {Object} [options] - Installation options
61
+ * @param {string} [options.specialist] - Specialist agent to use (e.g., 'claude')
62
+ * @param {boolean} [options.useAgent] - Use specialist agent if available (default: true)
63
+ * @returns {Promise<{success: boolean, installed: number, method: string}>}
64
+ */
65
+ async function install(projectRoot, agents, config, options = {}) {
66
+ const configPath = getConfigPath();
67
+
68
+ if (!configPath) {
69
+ throw new Error(`Unsupported platform: ${os.platform()}`);
70
+ }
71
+
72
+ const useAgent = options.useAgent !== false && options.specialist === 'claude';
73
+
74
+ if (useAgent) {
75
+ logger.info('Using agent Claude for native MCP integration...');
76
+ return await installViaCopilotAgent(projectRoot, agents, config);
77
+ } else {
78
+ logger.info('Using direct MCP configuration...');
79
+ return await installDirectMCP(projectRoot, agents, config);
80
+ }
81
+ }
82
+
83
+ /**
84
+ * Install via agent Claude (native integration)
85
+ *
86
+ * @param {string} projectRoot
87
+ * @param {string[]} agents
88
+ * @param {Object} config
89
+ * @returns {Promise<{success: boolean, installed: number, method: string}>}
90
+ */
91
+ async function installViaCopilotAgent(projectRoot, agents, config) {
92
+ const agentLauncher = require('../yanstaller/agent-launcher');
93
+
94
+ // Check if native launch is available
95
+ if (agentLauncher.supportsNativeLaunch('claude')) {
96
+ logger.info('\n🚀 Launching agent Claude for MCP integration...');
97
+
98
+ // Launch agent Claude with create-mcp-server action
99
+ const result = await agentLauncher.launch({
100
+ agent: 'claude',
101
+ platform: 'claude',
102
+ prompt: 'create-mcp-server'
103
+ });
104
+
105
+ if (result.success) {
106
+ return {
107
+ success: true,
108
+ installed: agents.length,
109
+ method: 'agent-claude-native'
110
+ };
111
+ } else {
112
+ logger.warn(`Native launch failed: ${result.error}`);
113
+ logger.info('Falling back to manual instructions...');
114
+ }
115
+ }
116
+
117
+ // Fallback: Manual instructions
118
+ logger.info('\n📝 To complete Claude Code integration:');
119
+ logger.info(' 1. Run: @bmad-agent-claude');
120
+ logger.info(' 2. Select option 1: Create MCP server for BYAN agents');
121
+ logger.info(' 3. Follow the guided setup\n');
122
+
123
+ return {
124
+ success: true,
125
+ installed: agents.length,
126
+ method: 'agent-claude-guided'
127
+ };
128
+ }
129
+
130
+ /**
131
+ * Install via direct MCP config update
132
+ *
133
+ * @param {string} projectRoot
134
+ * @param {string[]} agents
135
+ * @param {Object} config
136
+ * @returns {Promise<{success: boolean, installed: number, method: string}>}
137
+ */
138
+ async function installDirectMCP(projectRoot, agents, config) {
139
+ const configPath = getConfigPath();
140
+ const mcpServerPath = path.join(projectRoot, MCP_SERVER_FILENAME);
141
+
142
+ // Check if MCP server exists
143
+ if (!await fileUtils.exists(mcpServerPath)) {
144
+ logger.warn(`MCP server not found at: ${mcpServerPath}`);
145
+ logger.warn('Run @bmad-agent-claude to generate MCP server first.');
146
+
147
+ return {
148
+ success: false,
149
+ installed: 0,
150
+ method: 'direct-mcp-failed'
151
+ };
152
+ }
153
+
154
+ // Backup existing config
155
+ const backupPath = `${configPath}.backup`;
156
+ await fileUtils.copy(configPath, backupPath);
157
+ logger.info(`Backed up config to: ${backupPath}`);
158
+
159
+ // Read and update config
160
+ const existingConfig = await fileUtils.readJson(configPath);
161
+ existingConfig.mcpServers = existingConfig.mcpServers || {};
162
+
163
+ existingConfig.mcpServers.byan = {
164
+ command: 'node',
165
+ args: [mcpServerPath],
166
+ env: {
167
+ PROJECT_ROOT: projectRoot
168
+ }
169
+ };
170
+
171
+ // Write updated config
172
+ await fileUtils.writeJson(configPath, existingConfig, { spaces: 2 });
173
+ logger.info(`Updated MCP config: ${configPath}`);
174
+
175
+ return {
176
+ success: true,
177
+ installed: agents.length,
178
+ method: 'direct-mcp'
179
+ };
180
+ }
181
+
182
+ /**
183
+ * Get platform installation path
184
+ *
185
+ * @returns {string}
186
+ */
187
+ function getPath() {
188
+ return getConfigPath() || 'unknown';
189
+ }
190
+
191
+ module.exports = {
192
+ name: PLATFORM_NAME,
193
+ detect,
194
+ install,
195
+ getPath
196
+ };
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Codex Platform Support
3
+ *
4
+ * Detects and installs agents for Codex.
5
+ *
6
+ * @module platforms/codex
7
+ */
8
+
9
+ const path = require('path');
10
+ const fileUtils = require('../utils/file-utils');
11
+
12
+ const PLATFORM_NAME = 'Codex';
13
+ const PROMPTS_DIR = '.codex/prompts';
14
+
15
+ /**
16
+ * Detect if Codex is configured
17
+ *
18
+ * @returns {Promise<boolean>}
19
+ */
20
+ async function detect() {
21
+ // Check if .codex/prompts/ directory exists
22
+ return fileUtils.exists(PROMPTS_DIR);
23
+ }
24
+
25
+ /**
26
+ * Install agents for Codex
27
+ *
28
+ * @param {string} projectRoot - Project root directory
29
+ * @param {string[]} agents - Agent names to install
30
+ * @param {Object} config - Installation config
31
+ * @returns {Promise<{success: boolean, installed: number}>}
32
+ */
33
+ async function install(projectRoot, agents, config) {
34
+ const promptsDir = path.join(projectRoot, PROMPTS_DIR);
35
+ await fileUtils.ensureDir(promptsDir);
36
+
37
+ let installed = 0;
38
+
39
+ for (const agentName of agents) {
40
+ await generatePrompt(promptsDir, agentName, config);
41
+ installed++;
42
+ }
43
+
44
+ return {
45
+ success: true,
46
+ installed
47
+ };
48
+ }
49
+
50
+ /**
51
+ * Generate Codex prompt file
52
+ *
53
+ * @param {string} promptsDir - Prompts directory path
54
+ * @param {string} agentName - Agent name
55
+ * @param {Object} config - Installation config
56
+ * @returns {Promise<void>}
57
+ */
58
+ async function generatePrompt(promptsDir, agentName, config) {
59
+ const promptPath = path.join(promptsDir, `${agentName}.md`);
60
+
61
+ const content = `# ${agentName} Agent
62
+
63
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified.
64
+
65
+ <agent-activation CRITICAL="TRUE">
66
+ 1. LOAD the FULL agent file from {project-root}/_bmad/*/agents/${agentName}.md
67
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
68
+ 3. FOLLOW every step in the <activation> section precisely
69
+ 4. DISPLAY the welcome/greeting as instructed
70
+ 5. PRESENT the numbered menu
71
+ 6. WAIT for user input before proceeding
72
+ </agent-activation>
73
+ `;
74
+
75
+ await fileUtils.writeFile(promptPath, content);
76
+ }
77
+
78
+ /**
79
+ * Get platform installation path
80
+ *
81
+ * @returns {string}
82
+ */
83
+ function getPath() {
84
+ return PROMPTS_DIR;
85
+ }
86
+
87
+ module.exports = {
88
+ name: PLATFORM_NAME,
89
+ detect,
90
+ install,
91
+ getPath
92
+ };
@@ -0,0 +1,123 @@
1
+ /**
2
+ * GitHub Copilot CLI Platform Support
3
+ *
4
+ * Detects and installs agents for GitHub Copilot CLI.
5
+ *
6
+ * @module platforms/copilot-cli
7
+ */
8
+
9
+ const path = require('path');
10
+ const fileUtils = require('../utils/file-utils');
11
+ const yamlUtils = require('../utils/yaml-utils');
12
+ const { execSync } = require('child_process');
13
+
14
+ const PLATFORM_NAME = 'GitHub Copilot CLI';
15
+ const STUB_DIR = '.github/agents';
16
+
17
+ /**
18
+ * Detect if Copilot CLI is installed
19
+ *
20
+ * With 10s timeout protection to prevent hanging.
21
+ *
22
+ * @returns {Promise<boolean|{detected: boolean, error: string}>}
23
+ */
24
+ async function detect() {
25
+ // Timeout promise (10 seconds)
26
+ const timeoutPromise = new Promise((resolve) =>
27
+ setTimeout(() => resolve({
28
+ detected: false,
29
+ error: 'Detection timeout after 10s'
30
+ }), 10000)
31
+ );
32
+
33
+ // Detection promise
34
+ const detectionPromise = (async () => {
35
+ try {
36
+ // Check if github-copilot-cli is installed
37
+ execSync('which github-copilot-cli', { encoding: 'utf8', stdio: 'ignore' });
38
+ return true;
39
+ } catch {
40
+ // Also check for .github/agents/ directory
41
+ return fileUtils.exists(STUB_DIR);
42
+ }
43
+ })();
44
+
45
+ // Race between detection and timeout
46
+ return Promise.race([detectionPromise, timeoutPromise]);
47
+ }
48
+
49
+ /**
50
+ * Install agents for Copilot CLI
51
+ *
52
+ * @param {string} projectRoot - Project root directory
53
+ * @param {string[]} agents - Agent names to install
54
+ * @param {Object} config - Installation config
55
+ * @returns {Promise<{success: boolean, installed: number}>}
56
+ */
57
+ async function install(projectRoot, agents, config) {
58
+ const stubsDir = path.join(projectRoot, STUB_DIR);
59
+ await fileUtils.ensureDir(stubsDir);
60
+
61
+ let installed = 0;
62
+
63
+ for (const agentName of agents) {
64
+ await generateStub(stubsDir, agentName, config);
65
+ installed++;
66
+ }
67
+
68
+ return {
69
+ success: true,
70
+ installed
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Generate Copilot CLI stub with YAML frontmatter
76
+ *
77
+ * @param {string} stubsDir - Stubs directory path
78
+ * @param {string} agentName - Agent name
79
+ * @param {Object} config - Installation config
80
+ * @returns {Promise<void>}
81
+ */
82
+ async function generateStub(stubsDir, agentName, config) {
83
+ const stubPath = path.join(stubsDir, `${agentName}.md`);
84
+
85
+ const frontmatter = {
86
+ name: agentName,
87
+ description: `${agentName} agent from BYAN platform`
88
+ };
89
+
90
+ const content = `---
91
+ ${yamlUtils.dump(frontmatter).trim()}
92
+ ---
93
+
94
+ You must fully embody this agent's persona and follow all activation instructions exactly as specified. NEVER break character until given an exit command.
95
+
96
+ <agent-activation CRITICAL="TRUE">
97
+ 1. LOAD the FULL agent file from {project-root}/_bmad/*/agents/${agentName}.md
98
+ 2. READ its entire contents - this contains the complete agent persona, menu, and instructions
99
+ 3. FOLLOW every step in the <activation> section precisely
100
+ 4. DISPLAY the welcome/greeting as instructed
101
+ 5. PRESENT the numbered menu
102
+ 6. WAIT for user input before proceeding
103
+ </agent-activation>
104
+ `;
105
+
106
+ await fileUtils.writeFile(stubPath, content);
107
+ }
108
+
109
+ /**
110
+ * Get platform installation path
111
+ *
112
+ * @returns {string}
113
+ */
114
+ function getPath() {
115
+ return STUB_DIR;
116
+ }
117
+
118
+ module.exports = {
119
+ name: PLATFORM_NAME,
120
+ detect,
121
+ install,
122
+ getPath
123
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Platforms Index
3
+ *
4
+ * Exports all platform modules.
5
+ *
6
+ * @module platforms
7
+ */
8
+
9
+ module.exports = {
10
+ 'copilot-cli': require('./copilot-cli'),
11
+ 'vscode': require('./vscode'),
12
+ 'claude': require('./claude-code'),
13
+ 'codex': require('./codex')
14
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * VSCode Copilot Extension Platform Support
3
+ *
4
+ * Detects and installs agents for VSCode Copilot Extension.
5
+ * Same format as Copilot CLI.
6
+ *
7
+ * @module platforms/vscode
8
+ */
9
+
10
+ const copilotCli = require('./copilot-cli');
11
+
12
+ const PLATFORM_NAME = 'VSCode Copilot Extension';
13
+
14
+ /**
15
+ * Detect if VSCode with Copilot extension is installed
16
+ *
17
+ * @returns {Promise<boolean>}
18
+ */
19
+ async function detect() {
20
+ // VSCode uses same stub format as Copilot CLI
21
+ return copilotCli.detect();
22
+ }
23
+
24
+ /**
25
+ * Install agents for VSCode
26
+ *
27
+ * @param {string} projectRoot - Project root directory
28
+ * @param {string[]} agents - Agent names to install
29
+ * @param {Object} config - Installation config
30
+ * @returns {Promise<{success: boolean, installed: number}>}
31
+ */
32
+ async function install(projectRoot, agents, config) {
33
+ // Reuse Copilot CLI installation (same format)
34
+ return copilotCli.install(projectRoot, agents, config);
35
+ }
36
+
37
+ /**
38
+ * Get platform installation path
39
+ *
40
+ * @returns {string}
41
+ */
42
+ function getPath() {
43
+ return copilotCli.getPath();
44
+ }
45
+
46
+ module.exports = {
47
+ name: PLATFORM_NAME,
48
+ detect,
49
+ install,
50
+ getPath
51
+ };