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.
- package/bin/create-byan-agent-v2.js +1 -1
- package/lib/domain-questions.js +235 -0
- package/lib/errors.js +61 -0
- package/lib/exit-codes.js +54 -0
- package/lib/phase2-chat.js +534 -0
- package/lib/platforms/claude-code.js +196 -0
- package/lib/platforms/codex.js +92 -0
- package/lib/platforms/copilot-cli.js +123 -0
- package/lib/platforms/index.js +14 -0
- package/lib/platforms/vscode.js +51 -0
- package/lib/project-agents-generator.js +238 -0
- package/lib/utils/config-loader.js +79 -0
- package/lib/utils/file-utils.js +104 -0
- package/lib/utils/git-detector.js +35 -0
- package/lib/utils/logger.js +64 -0
- package/lib/utils/node-detector.js +58 -0
- package/lib/utils/os-detector.js +74 -0
- package/lib/utils/yaml-utils.js +87 -0
- package/lib/yanstaller/agent-launcher.js +348 -0
- package/lib/yanstaller/backuper.js +108 -0
- package/lib/yanstaller/detector.js +141 -0
- package/lib/yanstaller/index.js +139 -0
- package/lib/yanstaller/installer.js +140 -0
- package/lib/yanstaller/interviewer.js +88 -0
- package/lib/yanstaller/platform-selector.js +328 -0
- package/lib/yanstaller/recommender.js +102 -0
- package/lib/yanstaller/troubleshooter.js +89 -0
- package/lib/yanstaller/validator.js +198 -0
- package/lib/yanstaller/wizard.js +109 -0
- package/package.json +3 -1
- package/setup-turbo-whisper.js +687 -0
|
@@ -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
|
+
};
|