create-byan-agent 1.1.3 → 1.2.0
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/CHANGELOG.md +250 -202
- package/LICENSE +21 -21
- package/README.md +1245 -421
- package/bin/create-byan-agent-backup.js +220 -220
- package/bin/create-byan-agent-fixed.js +301 -301
- package/bin/create-byan-agent.js +322 -322
- package/lib/errors.js +61 -0
- package/lib/exit-codes.js +54 -0
- package/lib/platforms/claude-code.js +113 -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/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/backuper.js +308 -0
- package/lib/yanstaller/detector.js +141 -0
- package/lib/yanstaller/index.js +93 -0
- package/lib/yanstaller/installer.js +225 -0
- package/lib/yanstaller/interviewer.js +250 -0
- package/lib/yanstaller/recommender.js +298 -0
- package/lib/yanstaller/troubleshooter.js +498 -0
- package/lib/yanstaller/validator.js +578 -0
- package/lib/yanstaller/wizard.js +211 -0
- package/package.json +61 -55
- package/templates/.github/agents/bmad-agent-bmad-master.md +15 -15
- package/templates/.github/agents/bmad-agent-bmb-agent-builder.md +15 -15
- package/templates/.github/agents/bmad-agent-bmb-module-builder.md +15 -15
- package/templates/.github/agents/bmad-agent-bmb-workflow-builder.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-analyst.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-architect.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-dev.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-pm.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-quick-flow-solo-dev.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-quinn.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-sm.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-tech-writer.md +15 -15
- package/templates/.github/agents/bmad-agent-bmm-ux-designer.md +15 -15
- package/templates/.github/agents/bmad-agent-byan-test.md +32 -0
- package/templates/.github/agents/bmad-agent-byan.md +224 -224
- package/templates/.github/agents/bmad-agent-carmack.md +18 -0
- package/templates/.github/agents/bmad-agent-cis-brainstorming-coach.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-creative-problem-solver.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-design-thinking-coach.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-innovation-strategist.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-presentation-master.md +15 -15
- package/templates/.github/agents/bmad-agent-cis-storyteller.md +15 -15
- package/templates/.github/agents/bmad-agent-marc.md +48 -48
- package/templates/.github/agents/bmad-agent-patnote.md +48 -0
- package/templates/.github/agents/bmad-agent-rachid.md +47 -47
- package/templates/.github/agents/bmad-agent-tea-tea.md +15 -15
- package/templates/.github/agents/bmad-agent-test-dynamic.md +21 -0
- package/templates/.github/agents/expert-merise-agile.md +1 -0
- package/templates/.github/agents/franck.md +379 -0
- package/templates/_bmad/bmb/agents/agent-builder.md +59 -59
- package/templates/_bmad/bmb/agents/byan-test.md +116 -116
- package/templates/_bmad/bmb/agents/byan.md +215 -215
- package/templates/_bmad/bmb/agents/marc.md +303 -303
- package/templates/_bmad/bmb/agents/module-builder.md +60 -60
- package/templates/_bmad/bmb/agents/patnote.md +495 -495
- package/templates/_bmad/bmb/agents/rachid.md +184 -184
- package/templates/_bmad/bmb/agents/workflow-builder.md +61 -61
- package/templates/_bmad/bmb/workflows/byan/data/mantras.yaml +272 -272
- package/templates/_bmad/bmb/workflows/byan/data/templates.yaml +59 -59
- package/templates/_bmad/bmb/workflows/byan/delete-agent-workflow.md +657 -657
- package/templates/_bmad/bmb/workflows/byan/edit-agent-workflow.md +688 -688
- package/templates/_bmad/bmb/workflows/byan/interview-workflow.md +753 -753
- package/templates/_bmad/bmb/workflows/byan/quick-create-workflow.md +450 -450
- package/templates/_bmad/bmb/workflows/byan/templates/base-agent-template.md +79 -79
- package/templates/_bmad/bmb/workflows/byan/validate-agent-workflow.md +676 -676
- package/templates/_bmad/core/agents/carmack.md +238 -238
package/lib/errors.js
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Error Classes
|
|
3
|
+
*
|
|
4
|
+
* @module errors
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class YanInstallerError extends Error {
|
|
8
|
+
constructor(message, options) {
|
|
9
|
+
super(message, options);
|
|
10
|
+
this.name = 'YanInstallerError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
class NodeVersionError extends YanInstallerError {
|
|
15
|
+
constructor(required, current) {
|
|
16
|
+
super(`Node.js ${required}+ required, got ${current}`);
|
|
17
|
+
this.name = 'NodeVersionError';
|
|
18
|
+
this.required = required;
|
|
19
|
+
this.current = current;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
class PlatformNotFoundError extends YanInstallerError {
|
|
24
|
+
constructor(platform) {
|
|
25
|
+
super(`Platform not found: ${platform}`);
|
|
26
|
+
this.name = 'PlatformNotFoundError';
|
|
27
|
+
this.platform = platform;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class PermissionError extends YanInstallerError {
|
|
32
|
+
constructor(path) {
|
|
33
|
+
super(`Permission denied: ${path}`);
|
|
34
|
+
this.name = 'PermissionError';
|
|
35
|
+
this.path = path;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
class ValidationError extends YanInstallerError {
|
|
40
|
+
constructor(message, failures) {
|
|
41
|
+
super(message);
|
|
42
|
+
this.name = 'ValidationError';
|
|
43
|
+
this.failures = failures;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
class BackupError extends YanInstallerError {
|
|
48
|
+
constructor(message, options) {
|
|
49
|
+
super(message, options);
|
|
50
|
+
this.name = 'BackupError';
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
module.exports = {
|
|
55
|
+
YanInstallerError,
|
|
56
|
+
NodeVersionError,
|
|
57
|
+
PlatformNotFoundError,
|
|
58
|
+
PermissionError,
|
|
59
|
+
ValidationError,
|
|
60
|
+
BackupError
|
|
61
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exit Codes
|
|
3
|
+
*
|
|
4
|
+
* Standard exit codes for YANSTALLER CLI.
|
|
5
|
+
*
|
|
6
|
+
* @module exit-codes
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
module.exports = {
|
|
10
|
+
/**
|
|
11
|
+
* Success - Installation completed without errors
|
|
12
|
+
*/
|
|
13
|
+
SUCCESS: 0,
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Node.js version too old (< 18.0.0)
|
|
17
|
+
*/
|
|
18
|
+
NODE_VERSION_ERROR: 1,
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Permission denied (file system access)
|
|
22
|
+
*/
|
|
23
|
+
PERMISSION_ERROR: 2,
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Post-installation validation failed
|
|
27
|
+
*/
|
|
28
|
+
VALIDATION_FAILED: 3,
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Installation process failed
|
|
32
|
+
*/
|
|
33
|
+
INSTALLATION_FAILED: 4,
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Backup operation failed
|
|
37
|
+
*/
|
|
38
|
+
BACKUP_FAILED: 5,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Platform not found or not supported
|
|
42
|
+
*/
|
|
43
|
+
PLATFORM_ERROR: 6,
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* User cancelled installation
|
|
47
|
+
*/
|
|
48
|
+
USER_CANCELLED: 7,
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Unknown error
|
|
52
|
+
*/
|
|
53
|
+
UNKNOWN_ERROR: 99
|
|
54
|
+
};
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Platform Support
|
|
3
|
+
*
|
|
4
|
+
* Detects and installs MCP server config for Claude Code.
|
|
5
|
+
*
|
|
6
|
+
* @module platforms/claude-code
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const os = require('os');
|
|
11
|
+
const fileUtils = require('../utils/file-utils');
|
|
12
|
+
|
|
13
|
+
const PLATFORM_NAME = 'Claude Code';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Get config path for current platform
|
|
17
|
+
*
|
|
18
|
+
* @returns {string|null}
|
|
19
|
+
*/
|
|
20
|
+
function getConfigPath() {
|
|
21
|
+
const platform = os.platform();
|
|
22
|
+
const home = os.homedir();
|
|
23
|
+
|
|
24
|
+
switch (platform) {
|
|
25
|
+
case 'darwin':
|
|
26
|
+
return path.join(home, 'Library/Application Support/Claude/claude_desktop_config.json');
|
|
27
|
+
case 'win32':
|
|
28
|
+
return path.join(home, 'AppData/Roaming/Claude/claude_desktop_config.json');
|
|
29
|
+
case 'linux':
|
|
30
|
+
return path.join(home, '.config/Claude/claude_desktop_config.json');
|
|
31
|
+
default:
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Detect if Claude Code is installed
|
|
38
|
+
*
|
|
39
|
+
* @returns {Promise<boolean>}
|
|
40
|
+
*/
|
|
41
|
+
async function detect() {
|
|
42
|
+
const configPath = getConfigPath();
|
|
43
|
+
if (!configPath) return false;
|
|
44
|
+
|
|
45
|
+
return fileUtils.exists(configPath);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Install MCP server config for Claude Code
|
|
50
|
+
*
|
|
51
|
+
* @param {string} projectRoot - Project root directory
|
|
52
|
+
* @param {string[]} agents - Agent names to install
|
|
53
|
+
* @param {Object} config - Installation config
|
|
54
|
+
* @returns {Promise<{success: boolean, installed: number}>}
|
|
55
|
+
*/
|
|
56
|
+
async function install(projectRoot, agents, config) {
|
|
57
|
+
const configPath = getConfigPath();
|
|
58
|
+
|
|
59
|
+
if (!configPath) {
|
|
60
|
+
throw new Error(`Unsupported platform: ${os.platform()}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Read existing config or create new
|
|
64
|
+
let desktopConfig = {};
|
|
65
|
+
if (await fileUtils.exists(configPath)) {
|
|
66
|
+
const content = await fileUtils.readFile(configPath, 'utf8');
|
|
67
|
+
desktopConfig = JSON.parse(content);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Ensure mcpServers exists
|
|
71
|
+
if (!desktopConfig.mcpServers) {
|
|
72
|
+
desktopConfig.mcpServers = {};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Add BYAN MCP server if not exists
|
|
76
|
+
if (!desktopConfig.mcpServers.byan) {
|
|
77
|
+
desktopConfig.mcpServers.byan = {
|
|
78
|
+
command: 'npx',
|
|
79
|
+
args: ['-y', '@byan/mcp-server'],
|
|
80
|
+
env: {
|
|
81
|
+
BYAN_PROJECT_ROOT: projectRoot
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Write updated config
|
|
87
|
+
await fileUtils.ensureDir(path.dirname(configPath));
|
|
88
|
+
await fileUtils.writeFile(
|
|
89
|
+
configPath,
|
|
90
|
+
JSON.stringify(desktopConfig, null, 2)
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
return {
|
|
94
|
+
success: true,
|
|
95
|
+
installed: agents.length
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Get platform installation path
|
|
101
|
+
*
|
|
102
|
+
* @returns {string}
|
|
103
|
+
*/
|
|
104
|
+
function getPath() {
|
|
105
|
+
return getConfigPath() || 'unknown';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
name: PLATFORM_NAME,
|
|
110
|
+
detect,
|
|
111
|
+
install,
|
|
112
|
+
getPath
|
|
113
|
+
};
|
|
@@ -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
|
+
};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Config Loader Utility
|
|
3
|
+
*
|
|
4
|
+
* Loads configuration files with variable resolution.
|
|
5
|
+
*
|
|
6
|
+
* @module utils/config-loader
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const yamlUtils = require('./yaml-utils');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Load config file and resolve variables
|
|
14
|
+
*
|
|
15
|
+
* @param {string} configPath - Path to config.yaml
|
|
16
|
+
* @param {Object} context - Context for variable resolution
|
|
17
|
+
* @returns {Promise<Object>}
|
|
18
|
+
*/
|
|
19
|
+
async function loadConfig(configPath, context = {}) {
|
|
20
|
+
const config = await yamlUtils.readYAML(configPath);
|
|
21
|
+
return resolveVariables(config, context);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Resolve variables in config object
|
|
26
|
+
*
|
|
27
|
+
* @param {Object} config - Config object
|
|
28
|
+
* @param {Object} context - Context for variable resolution
|
|
29
|
+
* @returns {Object}
|
|
30
|
+
*/
|
|
31
|
+
function resolveVariables(config, context) {
|
|
32
|
+
const resolved = {};
|
|
33
|
+
|
|
34
|
+
for (const [key, value] of Object.entries(config)) {
|
|
35
|
+
if (typeof value === 'string') {
|
|
36
|
+
resolved[key] = resolveVariable(value, context);
|
|
37
|
+
} else if (typeof value === 'object' && value !== null) {
|
|
38
|
+
resolved[key] = resolveVariables(value, context);
|
|
39
|
+
} else {
|
|
40
|
+
resolved[key] = value;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return resolved;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Resolve single variable string
|
|
49
|
+
*
|
|
50
|
+
* @param {string} value - Value with potential variables
|
|
51
|
+
* @param {Object} context - Context for variable resolution
|
|
52
|
+
* @returns {string}
|
|
53
|
+
*/
|
|
54
|
+
function resolveVariable(value, context) {
|
|
55
|
+
let resolved = value;
|
|
56
|
+
|
|
57
|
+
// Replace {project-root}
|
|
58
|
+
if (context.projectRoot) {
|
|
59
|
+
resolved = resolved.replace(/\{project-root\}/g, context.projectRoot);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Replace {output_folder}
|
|
63
|
+
if (context.outputFolder) {
|
|
64
|
+
resolved = resolved.replace(/\{output_folder\}/g, context.outputFolder);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Replace {user_name}
|
|
68
|
+
if (context.userName) {
|
|
69
|
+
resolved = resolved.replace(/\{user_name\}/g, context.userName);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return resolved;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports = {
|
|
76
|
+
loadConfig,
|
|
77
|
+
resolveVariables,
|
|
78
|
+
resolveVariable
|
|
79
|
+
};
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* File Utilities
|
|
3
|
+
*
|
|
4
|
+
* Wrapper around fs-extra for common file operations.
|
|
5
|
+
*
|
|
6
|
+
* @module utils/file-utils
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs-extra');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Copy file or directory
|
|
14
|
+
*
|
|
15
|
+
* @param {string} src - Source path
|
|
16
|
+
* @param {string} dest - Destination path
|
|
17
|
+
* @returns {Promise<void>}
|
|
18
|
+
*/
|
|
19
|
+
async function copy(src, dest) {
|
|
20
|
+
await fs.copy(src, dest);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Check if path exists
|
|
25
|
+
*
|
|
26
|
+
* @param {string} filePath - File or directory path
|
|
27
|
+
* @returns {Promise<boolean>}
|
|
28
|
+
*/
|
|
29
|
+
async function exists(filePath) {
|
|
30
|
+
return fs.pathExists(filePath);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Ensure directory exists (create if not)
|
|
35
|
+
*
|
|
36
|
+
* @param {string} dirPath - Directory path
|
|
37
|
+
* @returns {Promise<void>}
|
|
38
|
+
*/
|
|
39
|
+
async function ensureDir(dirPath) {
|
|
40
|
+
await fs.ensureDir(dirPath);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Remove file or directory
|
|
45
|
+
*
|
|
46
|
+
* @param {string} filePath - File or directory path
|
|
47
|
+
* @returns {Promise<void>}
|
|
48
|
+
*/
|
|
49
|
+
async function remove(filePath) {
|
|
50
|
+
await fs.remove(filePath);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Read JSON file
|
|
55
|
+
*
|
|
56
|
+
* @param {string} filePath - JSON file path
|
|
57
|
+
* @returns {Promise<Object>}
|
|
58
|
+
*/
|
|
59
|
+
async function readJSON(filePath) {
|
|
60
|
+
return fs.readJSON(filePath);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Write JSON file
|
|
65
|
+
*
|
|
66
|
+
* @param {string} filePath - JSON file path
|
|
67
|
+
* @param {Object} data - Data to write
|
|
68
|
+
* @returns {Promise<void>}
|
|
69
|
+
*/
|
|
70
|
+
async function writeJSON(filePath, data) {
|
|
71
|
+
await fs.writeJSON(filePath, data, { spaces: 2 });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Read text file
|
|
76
|
+
*
|
|
77
|
+
* @param {string} filePath - Text file path
|
|
78
|
+
* @returns {Promise<string>}
|
|
79
|
+
*/
|
|
80
|
+
async function readFile(filePath) {
|
|
81
|
+
return fs.readFile(filePath, 'utf8');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Write text file
|
|
86
|
+
*
|
|
87
|
+
* @param {string} filePath - Text file path
|
|
88
|
+
* @param {string} content - Content to write
|
|
89
|
+
* @returns {Promise<void>}
|
|
90
|
+
*/
|
|
91
|
+
async function writeFile(filePath, content) {
|
|
92
|
+
await fs.writeFile(filePath, content, 'utf8');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = {
|
|
96
|
+
copy,
|
|
97
|
+
exists,
|
|
98
|
+
ensureDir,
|
|
99
|
+
remove,
|
|
100
|
+
readJSON,
|
|
101
|
+
writeJSON,
|
|
102
|
+
readFile,
|
|
103
|
+
writeFile
|
|
104
|
+
};
|