@bugzy-ai/bugzy 1.2.1 → 1.4.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/README.md +30 -9
- package/dist/cli/index.cjs +549 -155
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +552 -158
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +96 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +96 -33
- package/dist/index.js.map +1 -1
- package/dist/subagents/index.cjs +6 -3
- package/dist/subagents/index.cjs.map +1 -1
- package/dist/subagents/index.js +6 -3
- package/dist/subagents/index.js.map +1 -1
- package/dist/subagents/metadata.cjs +6 -3
- package/dist/subagents/metadata.cjs.map +1 -1
- package/dist/subagents/metadata.js +6 -3
- package/dist/subagents/metadata.js.map +1 -1
- package/dist/tasks/index.cjs +28 -29
- package/dist/tasks/index.cjs.map +1 -1
- package/dist/tasks/index.js +28 -29
- package/dist/tasks/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/init/AGENTS.md +155 -0
package/dist/cli/index.cjs
CHANGED
|
@@ -568,7 +568,9 @@ Document all findings including:
|
|
|
568
568
|
\`\`\`
|
|
569
569
|
|
|
570
570
|
#### 3.2 Launch Test Runner Agent
|
|
571
|
-
|
|
571
|
+
{{INVOKE_TEST_RUNNER}}
|
|
572
|
+
|
|
573
|
+
Execute the exploration test case with special exploration instructions:
|
|
572
574
|
|
|
573
575
|
\`\`\`
|
|
574
576
|
Execute the exploration test case at ./test-cases/EXPLORATION-TEMP.md with focus on discovery and documentation.
|
|
@@ -1039,10 +1041,10 @@ Before invoking the agent, identify the test cases for the current area:
|
|
|
1039
1041
|
|
|
1040
1042
|
#### Step 2.2: Invoke test-code-generator Agent
|
|
1041
1043
|
|
|
1042
|
-
|
|
1044
|
+
{{INVOKE_TEST_CODE_GENERATOR}} for the current area with the following context:
|
|
1043
1045
|
|
|
1044
1046
|
**Agent Invocation:**
|
|
1045
|
-
"
|
|
1047
|
+
"Automate test cases for the [AREA_NAME] area.
|
|
1046
1048
|
|
|
1047
1049
|
**Context:**
|
|
1048
1050
|
- Area: [AREA_NAME]
|
|
@@ -1182,10 +1184,10 @@ Provide a comprehensive summary showing:
|
|
|
1182
1184
|
role: "documentation-researcher",
|
|
1183
1185
|
contentBlock: `#### 1.4 Gather Product Documentation
|
|
1184
1186
|
|
|
1185
|
-
|
|
1187
|
+
{{INVOKE_DOCUMENTATION_RESEARCHER}} to gather comprehensive product documentation:
|
|
1186
1188
|
|
|
1187
1189
|
\`\`\`
|
|
1188
|
-
|
|
1190
|
+
Explore all available product documentation, specifically focusing on:
|
|
1189
1191
|
- UI elements and workflows
|
|
1190
1192
|
- User interactions and navigation paths
|
|
1191
1193
|
- Form fields and validation rules
|
|
@@ -1199,10 +1201,9 @@ Use the documentation-researcher agent to explore all available product document
|
|
|
1199
1201
|
role: "team-communicator",
|
|
1200
1202
|
contentBlock: `### Step 4.5: Team Communication
|
|
1201
1203
|
|
|
1202
|
-
|
|
1204
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to notify the product team about the new test cases and automated tests:
|
|
1203
1205
|
|
|
1204
1206
|
\`\`\`
|
|
1205
|
-
Use the team-communicator agent to:
|
|
1206
1207
|
1. Post an update about test case and automation creation
|
|
1207
1208
|
2. Provide summary of coverage:
|
|
1208
1209
|
- Number of manual test cases created
|
|
@@ -1471,10 +1472,10 @@ Provide a summary of:
|
|
|
1471
1472
|
role: "documentation-researcher",
|
|
1472
1473
|
contentBlock: `### Step 2: Gather comprehensive project documentation
|
|
1473
1474
|
|
|
1474
|
-
|
|
1475
|
+
{{INVOKE_DOCUMENTATION_RESEARCHER}} to explore and gather all available project information and other documentation sources. This ensures the test plan is based on complete and current information.
|
|
1475
1476
|
|
|
1476
1477
|
\`\`\`
|
|
1477
|
-
|
|
1478
|
+
Explore all available project documentation related to: $ARGUMENTS
|
|
1478
1479
|
|
|
1479
1480
|
Specifically gather:
|
|
1480
1481
|
- Product specifications and requirements
|
|
@@ -1499,10 +1500,9 @@ The agent will:
|
|
|
1499
1500
|
role: "team-communicator",
|
|
1500
1501
|
contentBlock: `### Step 7.5: Team Communication
|
|
1501
1502
|
|
|
1502
|
-
|
|
1503
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to notify the product team about the new test plan:
|
|
1503
1504
|
|
|
1504
1505
|
\`\`\`
|
|
1505
|
-
Use the team-communicator agent to:
|
|
1506
1506
|
1. Post an update about the test plan creation
|
|
1507
1507
|
2. Provide a brief summary of coverage areas and key features
|
|
1508
1508
|
3. Mention any areas that need exploration or clarification
|
|
@@ -1755,7 +1755,7 @@ Classify the ambiguity level to determine appropriate response:
|
|
|
1755
1755
|
#### Clarification Approach by Severity
|
|
1756
1756
|
|
|
1757
1757
|
**For CRITICAL/HIGH ambiguity:**
|
|
1758
|
-
1. **
|
|
1758
|
+
1. **{{INVOKE_TEAM_COMMUNICATOR}} to ask specific questions**
|
|
1759
1759
|
2. **WAIT for response before proceeding**
|
|
1760
1760
|
3. **Document the clarification request in event history**
|
|
1761
1761
|
|
|
@@ -2028,7 +2028,7 @@ ${KNOWLEDGE_BASE_UPDATE_INSTRUCTIONS}`,
|
|
|
2028
2028
|
contentBlock: `#### 3.3 Use Documentation Researcher if Needed
|
|
2029
2029
|
For events mentioning unknown features or components:
|
|
2030
2030
|
\`\`\`
|
|
2031
|
-
|
|
2031
|
+
{{INVOKE_DOCUMENTATION_RESEARCHER}} to find information about: [component/feature]
|
|
2032
2032
|
\`\`\``
|
|
2033
2033
|
},
|
|
2034
2034
|
{
|
|
@@ -2037,7 +2037,7 @@ Use documentation-researcher agent to find information about: [component/feature
|
|
|
2037
2037
|
|
|
2038
2038
|
When an issue needs to be tracked (task type: report_bug or update_story):
|
|
2039
2039
|
\`\`\`
|
|
2040
|
-
|
|
2040
|
+
{{INVOKE_ISSUE_TRACKER}}
|
|
2041
2041
|
1. Check for duplicate issues in the tracking system
|
|
2042
2042
|
2. For bugs: Create detailed bug report with:
|
|
2043
2043
|
- Clear, descriptive title
|
|
@@ -2315,7 +2315,7 @@ For each failed test:
|
|
|
2315
2315
|
For each test classified as **[TEST ISSUE]**, use the test-debugger-fixer agent to automatically fix the test:
|
|
2316
2316
|
|
|
2317
2317
|
\`\`\`
|
|
2318
|
-
|
|
2318
|
+
{{INVOKE_TEST_DEBUGGER_FIXER}}
|
|
2319
2319
|
|
|
2320
2320
|
For each failed test classified as a test issue (not a product bug), provide:
|
|
2321
2321
|
- Test run timestamp: [from manifest.timestamp]
|
|
@@ -2410,7 +2410,7 @@ After triage in Step 5.1, for tests classified as **[PRODUCT BUG]**, use the iss
|
|
|
2410
2410
|
For each bug to report, use the issue-tracker agent:
|
|
2411
2411
|
|
|
2412
2412
|
\`\`\`
|
|
2413
|
-
|
|
2413
|
+
{{INVOKE_ISSUE_TRACKER}}
|
|
2414
2414
|
1. Check for duplicate bugs in the tracking system
|
|
2415
2415
|
- The agent will automatically search for similar existing issues
|
|
2416
2416
|
- It maintains memory of recently reported issues
|
|
@@ -2481,10 +2481,11 @@ After issue tracker agent completes, create a summary:
|
|
|
2481
2481
|
role: "team-communicator",
|
|
2482
2482
|
contentBlock: `### Step 6: Team Communication
|
|
2483
2483
|
|
|
2484
|
-
|
|
2484
|
+
{{INVOKE_TEAM_COMMUNICATOR}}
|
|
2485
|
+
|
|
2486
|
+
Notify the product team about test execution:
|
|
2485
2487
|
|
|
2486
2488
|
\`\`\`
|
|
2487
|
-
Use the team-communicator agent to:
|
|
2488
2489
|
1. Post test execution summary with key statistics
|
|
2489
2490
|
2. Highlight critical failures that need immediate attention
|
|
2490
2491
|
3. Share important learnings about product behavior
|
|
@@ -2828,7 +2829,7 @@ Read and analyze the JSON report:
|
|
|
2828
2829
|
For each test classified as **[TEST ISSUE]**, use the test-debugger-fixer agent to automatically fix the test:
|
|
2829
2830
|
|
|
2830
2831
|
\`\`\`
|
|
2831
|
-
|
|
2832
|
+
{{INVOKE_TEST_DEBUGGER_FIXER}}
|
|
2832
2833
|
|
|
2833
2834
|
For each failed test classified as a test issue (not a product bug), provide:
|
|
2834
2835
|
- Test file path: [from JSON report]
|
|
@@ -2869,7 +2870,7 @@ Classification guidelines:
|
|
|
2869
2870
|
#### 4A.4 Fix Test Issues Automatically
|
|
2870
2871
|
|
|
2871
2872
|
For tests classified as [TEST ISSUE]:
|
|
2872
|
-
-
|
|
2873
|
+
- {{INVOKE_TEST_DEBUGGER_FIXER}} to analyze and fix
|
|
2873
2874
|
- Agent debugs with browser if needed
|
|
2874
2875
|
- Applies fix (selector update, wait condition, assertion correction)
|
|
2875
2876
|
- Reruns test to verify fix (10x for flaky tests)
|
|
@@ -2885,7 +2886,7 @@ Track fixed tests with:
|
|
|
2885
2886
|
{{ISSUE_TRACKER_INSTRUCTIONS}}
|
|
2886
2887
|
|
|
2887
2888
|
For tests classified as [PRODUCT BUG]:
|
|
2888
|
-
-
|
|
2889
|
+
- {{INVOKE_ISSUE_TRACKER}} to create bug reports
|
|
2889
2890
|
- Agent checks for duplicates automatically
|
|
2890
2891
|
- Creates detailed report with:
|
|
2891
2892
|
- Title, description, reproduction steps
|
|
@@ -3201,10 +3202,10 @@ Format as comprehensive markdown report for terminal display:
|
|
|
3201
3202
|
|
|
3202
3203
|
{{TEAM_COMMUNICATOR_INSTRUCTIONS}}
|
|
3203
3204
|
|
|
3204
|
-
|
|
3205
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to post concise results to Slack thread:
|
|
3205
3206
|
|
|
3206
3207
|
\`\`\`
|
|
3207
|
-
|
|
3208
|
+
Post verification results.
|
|
3208
3209
|
|
|
3209
3210
|
**Channel**: [from CHANGE_CONTEXT.slackChannel]
|
|
3210
3211
|
**Thread**: [from CHANGE_CONTEXT.slackThread]
|
|
@@ -3385,10 +3386,10 @@ A successful verification includes:
|
|
|
3385
3386
|
role: "documentation-researcher",
|
|
3386
3387
|
contentBlock: `#### Research Project Documentation
|
|
3387
3388
|
|
|
3388
|
-
|
|
3389
|
+
{{INVOKE_DOCUMENTATION_RESEARCHER}} to gather comprehensive context about the changed features:
|
|
3389
3390
|
|
|
3390
3391
|
\`\`\`
|
|
3391
|
-
|
|
3392
|
+
Explore project documentation related to the changes.
|
|
3392
3393
|
|
|
3393
3394
|
Specifically gather:
|
|
3394
3395
|
- Product specifications for affected features
|
|
@@ -3420,10 +3421,9 @@ Use this information to:
|
|
|
3420
3421
|
role: "issue-tracker",
|
|
3421
3422
|
contentBlock: `#### Log Product Bugs
|
|
3422
3423
|
|
|
3423
|
-
For tests classified as **[PRODUCT BUG]**,
|
|
3424
|
+
For tests classified as **[PRODUCT BUG]**, {{INVOKE_ISSUE_TRACKER}} to log bugs:
|
|
3424
3425
|
|
|
3425
3426
|
\`\`\`
|
|
3426
|
-
Use issue-tracker agent to:
|
|
3427
3427
|
1. Check for duplicate bugs in the tracking system
|
|
3428
3428
|
- The agent will automatically search for similar existing issues
|
|
3429
3429
|
- It maintains memory of recently reported issues
|
|
@@ -3472,10 +3472,9 @@ Use issue-tracker agent to:
|
|
|
3472
3472
|
role: "team-communicator",
|
|
3473
3473
|
contentBlock: `#### Team Communication
|
|
3474
3474
|
|
|
3475
|
-
|
|
3475
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to share verification results (primarily for Slack trigger, but can be used for other triggers):
|
|
3476
3476
|
|
|
3477
3477
|
\`\`\`
|
|
3478
|
-
Use the team-communicator agent to:
|
|
3479
3478
|
1. Post verification results summary
|
|
3480
3479
|
2. Highlight critical failures that need immediate attention
|
|
3481
3480
|
3. Share bugs logged with issue tracker links
|
|
@@ -3605,6 +3604,7 @@ var import_chalk3 = __toESM(require("chalk"), 1);
|
|
|
3605
3604
|
// src/cli/commands/start.ts
|
|
3606
3605
|
init_cjs_shims();
|
|
3607
3606
|
var import_child_process = require("child_process");
|
|
3607
|
+
var path4 = __toESM(require("path"), 1);
|
|
3608
3608
|
var import_chalk = __toESM(require("chalk"), 1);
|
|
3609
3609
|
var import_ora = __toESM(require("ora"), 1);
|
|
3610
3610
|
|
|
@@ -3612,6 +3612,97 @@ var import_ora = __toESM(require("ora"), 1);
|
|
|
3612
3612
|
init_cjs_shims();
|
|
3613
3613
|
var fs = __toESM(require("fs"), 1);
|
|
3614
3614
|
var path = __toESM(require("path"), 1);
|
|
3615
|
+
|
|
3616
|
+
// src/core/tool-profile.ts
|
|
3617
|
+
init_cjs_shims();
|
|
3618
|
+
var DEFAULT_TOOL = "claude-code";
|
|
3619
|
+
var CLAUDE_CODE_PROFILE = {
|
|
3620
|
+
id: "claude-code",
|
|
3621
|
+
name: "Claude Code",
|
|
3622
|
+
cliCommand: "claude",
|
|
3623
|
+
commandsDir: ".claude/commands",
|
|
3624
|
+
agentsDir: ".claude/agents",
|
|
3625
|
+
mcpConfigPath: ".mcp.json",
|
|
3626
|
+
mcpFormat: "json",
|
|
3627
|
+
memoryFile: "CLAUDE.md",
|
|
3628
|
+
commandFrontmatter: true,
|
|
3629
|
+
agentFrontmatter: true,
|
|
3630
|
+
commandInvocationPrefix: "/",
|
|
3631
|
+
commandExtension: ".md",
|
|
3632
|
+
agentExtension: ".md"
|
|
3633
|
+
};
|
|
3634
|
+
var CURSOR_PROFILE = {
|
|
3635
|
+
id: "cursor",
|
|
3636
|
+
name: "Cursor",
|
|
3637
|
+
cliCommand: "cursor-agent",
|
|
3638
|
+
commandsDir: ".cursor/commands",
|
|
3639
|
+
agentsDir: ".cursor/agents",
|
|
3640
|
+
mcpConfigPath: ".cursor/mcp.json",
|
|
3641
|
+
mcpFormat: "json",
|
|
3642
|
+
memoryFile: "AGENTS.md",
|
|
3643
|
+
// Cursor now uses AGENTS.md (.cursorrules deprecated as of v0.45+)
|
|
3644
|
+
commandFrontmatter: false,
|
|
3645
|
+
// Cursor uses plain markdown
|
|
3646
|
+
agentFrontmatter: false,
|
|
3647
|
+
// Agent files are plain markdown for CLI invocation
|
|
3648
|
+
commandInvocationPrefix: "/",
|
|
3649
|
+
commandExtension: ".md",
|
|
3650
|
+
agentExtension: ".md"
|
|
3651
|
+
};
|
|
3652
|
+
var CODEX_PROFILE = {
|
|
3653
|
+
id: "codex",
|
|
3654
|
+
name: "Codex CLI",
|
|
3655
|
+
cliCommand: "codex",
|
|
3656
|
+
commandsDir: ".codex/prompts",
|
|
3657
|
+
// Codex uses prompts directory
|
|
3658
|
+
agentsDir: ".codex/agents",
|
|
3659
|
+
mcpConfigPath: ".codex/config.toml",
|
|
3660
|
+
// Project-local via CODEX_HOME
|
|
3661
|
+
mcpFormat: "toml",
|
|
3662
|
+
homeEnvVar: "CODEX_HOME",
|
|
3663
|
+
// Set to project root for project-local config
|
|
3664
|
+
memoryFile: "AGENTS.md",
|
|
3665
|
+
commandFrontmatter: true,
|
|
3666
|
+
// Codex prompts support frontmatter
|
|
3667
|
+
agentFrontmatter: false,
|
|
3668
|
+
// Agent files are plain markdown for CLI invocation
|
|
3669
|
+
commandInvocationPrefix: "/prompts:",
|
|
3670
|
+
commandExtension: ".md",
|
|
3671
|
+
agentExtension: ".md"
|
|
3672
|
+
};
|
|
3673
|
+
var TOOL_PROFILES = {
|
|
3674
|
+
"claude-code": CLAUDE_CODE_PROFILE,
|
|
3675
|
+
"cursor": CURSOR_PROFILE,
|
|
3676
|
+
"codex": CODEX_PROFILE
|
|
3677
|
+
};
|
|
3678
|
+
function getToolProfile(toolId) {
|
|
3679
|
+
const profile = TOOL_PROFILES[toolId];
|
|
3680
|
+
if (!profile) {
|
|
3681
|
+
throw new Error(`Unknown tool: ${toolId}`);
|
|
3682
|
+
}
|
|
3683
|
+
return profile;
|
|
3684
|
+
}
|
|
3685
|
+
function getToolOptions() {
|
|
3686
|
+
return [
|
|
3687
|
+
{
|
|
3688
|
+
value: "claude-code",
|
|
3689
|
+
label: "Claude Code (CLI or Cloud)",
|
|
3690
|
+
hint: "Anthropic's official CLI - recommended"
|
|
3691
|
+
},
|
|
3692
|
+
{
|
|
3693
|
+
value: "cursor",
|
|
3694
|
+
label: "Cursor (Experimental)",
|
|
3695
|
+
hint: "VS Code-based AI editor - experimental support"
|
|
3696
|
+
},
|
|
3697
|
+
{
|
|
3698
|
+
value: "codex",
|
|
3699
|
+
label: "Codex CLI (Experimental)",
|
|
3700
|
+
hint: "OpenAI's terminal-based agent - experimental support"
|
|
3701
|
+
}
|
|
3702
|
+
];
|
|
3703
|
+
}
|
|
3704
|
+
|
|
3705
|
+
// src/cli/utils/config.ts
|
|
3615
3706
|
async function loadConfig(configPath = ".bugzy/config.json") {
|
|
3616
3707
|
const fullPath = path.join(process.cwd(), configPath);
|
|
3617
3708
|
if (!fs.existsSync(fullPath)) {
|
|
@@ -3620,6 +3711,9 @@ async function loadConfig(configPath = ".bugzy/config.json") {
|
|
|
3620
3711
|
try {
|
|
3621
3712
|
const content = fs.readFileSync(fullPath, "utf-8");
|
|
3622
3713
|
const config = JSON.parse(content);
|
|
3714
|
+
if (!config.tool) {
|
|
3715
|
+
config.tool = DEFAULT_TOOL;
|
|
3716
|
+
}
|
|
3623
3717
|
return config;
|
|
3624
3718
|
} catch (error) {
|
|
3625
3719
|
console.error(`Error loading config from ${fullPath}:`, error);
|
|
@@ -3644,15 +3738,19 @@ function configExists(configPath = ".bugzy/config.json") {
|
|
|
3644
3738
|
const fullPath = path.join(process.cwd(), configPath);
|
|
3645
3739
|
return fs.existsSync(fullPath);
|
|
3646
3740
|
}
|
|
3647
|
-
function createDefaultConfig(projectName) {
|
|
3741
|
+
function createDefaultConfig(projectName, tool = DEFAULT_TOOL) {
|
|
3648
3742
|
return {
|
|
3649
3743
|
version: "1.0.0",
|
|
3744
|
+
tool,
|
|
3650
3745
|
project: {
|
|
3651
3746
|
name: projectName
|
|
3652
3747
|
},
|
|
3653
3748
|
subagents: {}
|
|
3654
3749
|
};
|
|
3655
3750
|
}
|
|
3751
|
+
function getToolFromConfig(config) {
|
|
3752
|
+
return config.tool || DEFAULT_TOOL;
|
|
3753
|
+
}
|
|
3656
3754
|
|
|
3657
3755
|
// src/cli/utils/env.ts
|
|
3658
3756
|
init_cjs_shims();
|
|
@@ -3715,13 +3813,19 @@ function validateEnvVars(mcpServers, envVars) {
|
|
|
3715
3813
|
init_cjs_shims();
|
|
3716
3814
|
var fs3 = __toESM(require("fs"), 1);
|
|
3717
3815
|
var path3 = __toESM(require("path"), 1);
|
|
3718
|
-
function validateProjectStructure() {
|
|
3816
|
+
async function validateProjectStructure() {
|
|
3817
|
+
const config = await loadConfig();
|
|
3818
|
+
const tool = config ? getToolFromConfig(config) : DEFAULT_TOOL;
|
|
3819
|
+
const toolProfile = getToolProfile(tool);
|
|
3719
3820
|
const requiredDirs = [
|
|
3720
3821
|
".bugzy",
|
|
3721
3822
|
".bugzy/runtime",
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3823
|
+
path3.dirname(toolProfile.commandsDir),
|
|
3824
|
+
// .claude, .cursor, or .codex
|
|
3825
|
+
toolProfile.commandsDir,
|
|
3826
|
+
// .claude/commands, .cursor/commands, .codex/prompts
|
|
3827
|
+
toolProfile.agentsDir
|
|
3828
|
+
// .claude/agents, .cursor/agents, .codex/agents
|
|
3725
3829
|
];
|
|
3726
3830
|
const requiredFiles = [
|
|
3727
3831
|
".bugzy/config.json",
|
|
@@ -3747,15 +3851,24 @@ function validateProjectStructure() {
|
|
|
3747
3851
|
}
|
|
3748
3852
|
return true;
|
|
3749
3853
|
}
|
|
3750
|
-
async function
|
|
3854
|
+
async function checkToolAvailable(command) {
|
|
3751
3855
|
const { spawn: spawn2 } = await import("child_process");
|
|
3856
|
+
const isWindows = process.platform === "win32";
|
|
3857
|
+
const checkCommand = isWindows ? "where" : "which";
|
|
3752
3858
|
return new Promise((resolve) => {
|
|
3753
|
-
const proc = spawn2(
|
|
3859
|
+
const proc = spawn2(checkCommand, [command], {
|
|
3860
|
+
shell: isWindows
|
|
3861
|
+
// Windows needs shell for 'where'
|
|
3862
|
+
});
|
|
3754
3863
|
proc.on("close", (code) => {
|
|
3755
|
-
|
|
3864
|
+
if (code !== 0) {
|
|
3865
|
+
console.warn(`Warning: Could not verify '${command}' is installed (${checkCommand} check failed). Continuing anyway...`);
|
|
3866
|
+
}
|
|
3867
|
+
resolve(true);
|
|
3756
3868
|
});
|
|
3757
3869
|
proc.on("error", () => {
|
|
3758
|
-
|
|
3870
|
+
console.warn(`Warning: Could not verify '${command}' is installed (${checkCommand} not available). Continuing anyway...`);
|
|
3871
|
+
resolve(true);
|
|
3759
3872
|
});
|
|
3760
3873
|
});
|
|
3761
3874
|
}
|
|
@@ -3795,9 +3908,11 @@ async function startSession(prompt) {
|
|
|
3795
3908
|
process.exit(1);
|
|
3796
3909
|
}
|
|
3797
3910
|
spinner.succeed(import_chalk.default.green("Configuration loaded"));
|
|
3911
|
+
const tool = getToolFromConfig(config);
|
|
3912
|
+
const toolProfile = getToolProfile(tool);
|
|
3798
3913
|
spinner = (0, import_ora.default)("Validating project structure").start();
|
|
3799
3914
|
try {
|
|
3800
|
-
validateProjectStructure();
|
|
3915
|
+
await validateProjectStructure();
|
|
3801
3916
|
spinner.succeed(import_chalk.default.green("Project structure validated"));
|
|
3802
3917
|
} catch (error) {
|
|
3803
3918
|
spinner.fail(import_chalk.default.red("Invalid project structure"));
|
|
@@ -3805,15 +3920,9 @@ async function startSession(prompt) {
|
|
|
3805
3920
|
console.log(import_chalk.default.yellow("\nRun"), import_chalk.default.cyan("bugzy setup"), import_chalk.default.yellow("to fix the project structure"));
|
|
3806
3921
|
process.exit(1);
|
|
3807
3922
|
}
|
|
3808
|
-
spinner = (0, import_ora.default)(
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
spinner.fail(import_chalk.default.red("Claude Code CLI not found"));
|
|
3812
|
-
console.log(import_chalk.default.yellow("\nPlease install Claude Code:"));
|
|
3813
|
-
console.log(import_chalk.default.cyan(" https://claude.com/claude-code"));
|
|
3814
|
-
process.exit(1);
|
|
3815
|
-
}
|
|
3816
|
-
spinner.succeed(import_chalk.default.green("Claude Code CLI found"));
|
|
3923
|
+
spinner = (0, import_ora.default)(`Checking ${toolProfile.name} availability`).start();
|
|
3924
|
+
await checkToolAvailable(toolProfile.cliCommand);
|
|
3925
|
+
spinner.succeed(import_chalk.default.green(`${toolProfile.name} CLI check complete`));
|
|
3817
3926
|
spinner = (0, import_ora.default)("Loading environment variables").start();
|
|
3818
3927
|
const envVars = loadEnvFiles();
|
|
3819
3928
|
const envCount = Object.keys(envVars).length;
|
|
@@ -3831,14 +3940,20 @@ async function startSession(prompt) {
|
|
|
3831
3940
|
process.exit(1);
|
|
3832
3941
|
}
|
|
3833
3942
|
spinner.succeed(import_chalk.default.green("All required MCP secrets present"));
|
|
3834
|
-
console.log(import_chalk.default.green.bold(
|
|
3943
|
+
console.log(import_chalk.default.green.bold(`
|
|
3944
|
+
\u{1F680} Launching ${toolProfile.name}...
|
|
3945
|
+
`));
|
|
3835
3946
|
const args = prompt ? [prompt] : [];
|
|
3836
|
-
const
|
|
3947
|
+
const spawnEnv = { ...process.env, ...envVars };
|
|
3948
|
+
if (toolProfile.homeEnvVar) {
|
|
3949
|
+
spawnEnv[toolProfile.homeEnvVar] = path4.join(process.cwd(), ".codex");
|
|
3950
|
+
}
|
|
3951
|
+
const child = (0, import_child_process.spawn)(toolProfile.cliCommand, args, {
|
|
3837
3952
|
cwd: process.cwd(),
|
|
3838
|
-
env:
|
|
3953
|
+
env: spawnEnv,
|
|
3839
3954
|
stdio: "inherit"
|
|
3840
3955
|
});
|
|
3841
|
-
|
|
3956
|
+
child.on("close", (code) => {
|
|
3842
3957
|
if (code === 0) {
|
|
3843
3958
|
console.log(import_chalk.default.green("\n\u2713 Session ended successfully"));
|
|
3844
3959
|
} else {
|
|
@@ -3846,15 +3961,16 @@ async function startSession(prompt) {
|
|
|
3846
3961
|
\u2713 Session ended (exit code: ${code})`));
|
|
3847
3962
|
}
|
|
3848
3963
|
});
|
|
3849
|
-
|
|
3850
|
-
console.error(import_chalk.default.red(
|
|
3964
|
+
child.on("error", (error) => {
|
|
3965
|
+
console.error(import_chalk.default.red(`
|
|
3966
|
+
\u2717 Error launching ${toolProfile.name}:`), error);
|
|
3851
3967
|
process.exit(1);
|
|
3852
3968
|
});
|
|
3853
3969
|
}
|
|
3854
3970
|
|
|
3855
3971
|
// src/cli/commands/setup.ts
|
|
3856
3972
|
init_cjs_shims();
|
|
3857
|
-
var
|
|
3973
|
+
var path11 = __toESM(require("path"), 1);
|
|
3858
3974
|
var import_chalk2 = __toESM(require("chalk"), 1);
|
|
3859
3975
|
var import_inquirer = __toESM(require("inquirer"), 1);
|
|
3860
3976
|
var import_ora2 = __toESM(require("ora"), 1);
|
|
@@ -6421,8 +6537,8 @@ var SUBAGENTS = {
|
|
|
6421
6537
|
description: "Automatically create and track bugs and issues",
|
|
6422
6538
|
icon: "bot",
|
|
6423
6539
|
integrations: [
|
|
6424
|
-
INTEGRATIONS.linear,
|
|
6425
|
-
INTEGRATIONS.jira,
|
|
6540
|
+
// INTEGRATIONS.linear,
|
|
6541
|
+
// INTEGRATIONS.jira,
|
|
6426
6542
|
INTEGRATIONS["jira-server"],
|
|
6427
6543
|
INTEGRATIONS.notion,
|
|
6428
6544
|
INTEGRATIONS.slack
|
|
@@ -6436,7 +6552,10 @@ var SUBAGENTS = {
|
|
|
6436
6552
|
name: "Documentation Researcher",
|
|
6437
6553
|
description: "Search and retrieve information from your documentation",
|
|
6438
6554
|
icon: "file-search",
|
|
6439
|
-
integrations: [
|
|
6555
|
+
integrations: [
|
|
6556
|
+
INTEGRATIONS.notion
|
|
6557
|
+
// INTEGRATIONS.confluence
|
|
6558
|
+
],
|
|
6440
6559
|
model: "sonnet",
|
|
6441
6560
|
color: "cyan",
|
|
6442
6561
|
version: "1.0.0"
|
|
@@ -6489,27 +6608,31 @@ function buildSubagentConfig(role, integration) {
|
|
|
6489
6608
|
// src/cli/generators/structure.ts
|
|
6490
6609
|
init_cjs_shims();
|
|
6491
6610
|
var fs4 = __toESM(require("fs"), 1);
|
|
6492
|
-
var
|
|
6493
|
-
async function createProjectStructure() {
|
|
6611
|
+
var path5 = __toESM(require("path"), 1);
|
|
6612
|
+
async function createProjectStructure(tool = DEFAULT_TOOL) {
|
|
6494
6613
|
const cwd = process.cwd();
|
|
6614
|
+
const toolProfile = getToolProfile(tool);
|
|
6495
6615
|
const bugzyDirs = [
|
|
6496
6616
|
".bugzy",
|
|
6497
6617
|
".bugzy/runtime",
|
|
6498
6618
|
".bugzy/runtime/templates"
|
|
6499
6619
|
];
|
|
6500
6620
|
for (const dir of bugzyDirs) {
|
|
6501
|
-
const dirPath =
|
|
6621
|
+
const dirPath = path5.join(cwd, dir);
|
|
6502
6622
|
if (!fs4.existsSync(dirPath)) {
|
|
6503
6623
|
fs4.mkdirSync(dirPath, { recursive: true });
|
|
6504
6624
|
}
|
|
6505
6625
|
}
|
|
6506
|
-
const
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6626
|
+
const toolDirs = [
|
|
6627
|
+
path5.dirname(toolProfile.commandsDir),
|
|
6628
|
+
// .claude, .cursor, or .codex
|
|
6629
|
+
toolProfile.commandsDir,
|
|
6630
|
+
// .claude/commands, .cursor/commands, .codex/prompts
|
|
6631
|
+
toolProfile.agentsDir
|
|
6632
|
+
// .claude/agents, .cursor/agents, .codex/agents
|
|
6510
6633
|
];
|
|
6511
|
-
for (const dir of
|
|
6512
|
-
const dirPath =
|
|
6634
|
+
for (const dir of toolDirs) {
|
|
6635
|
+
const dirPath = path5.join(cwd, dir);
|
|
6513
6636
|
if (!fs4.existsSync(dirPath)) {
|
|
6514
6637
|
fs4.mkdirSync(dirPath, { recursive: true });
|
|
6515
6638
|
}
|
|
@@ -6517,69 +6640,69 @@ async function createProjectStructure() {
|
|
|
6517
6640
|
await createRuntimeFiles();
|
|
6518
6641
|
}
|
|
6519
6642
|
function getTemplatesDir() {
|
|
6520
|
-
return
|
|
6643
|
+
return path5.join(__dirname, "../../templates/init");
|
|
6521
6644
|
}
|
|
6522
6645
|
async function createRuntimeFiles() {
|
|
6523
6646
|
const cwd = process.cwd();
|
|
6524
6647
|
const templatesDir = getTemplatesDir();
|
|
6525
|
-
const projectContextPath =
|
|
6648
|
+
const projectContextPath = path5.join(cwd, ".bugzy/runtime/project-context.md");
|
|
6526
6649
|
if (!fs4.existsSync(projectContextPath)) {
|
|
6527
|
-
const templatePath =
|
|
6650
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/project-context.md");
|
|
6528
6651
|
let content = fs4.readFileSync(templatePath, "utf-8");
|
|
6529
|
-
const projectName =
|
|
6652
|
+
const projectName = path5.basename(cwd);
|
|
6530
6653
|
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
|
|
6531
6654
|
content = content.replace(/\{\{CUSTOMER_NAME\}\}/g, "[To be filled]");
|
|
6532
6655
|
content = content.replace(/\{\{BUG_TRACKING_SYSTEM\}\}/g, "[To be filled]");
|
|
6533
6656
|
content = content.replace(/\{\{DOCUMENTATION_SYSTEM\}\}/g, "[To be filled]");
|
|
6534
6657
|
fs4.writeFileSync(projectContextPath, content, "utf-8");
|
|
6535
6658
|
}
|
|
6536
|
-
const testPlanTemplatePath =
|
|
6659
|
+
const testPlanTemplatePath = path5.join(cwd, ".bugzy/runtime/templates/test-plan-template.md");
|
|
6537
6660
|
if (!fs4.existsSync(testPlanTemplatePath)) {
|
|
6538
|
-
const templatePath =
|
|
6661
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/templates/test-plan-template.md");
|
|
6539
6662
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6540
6663
|
fs4.writeFileSync(testPlanTemplatePath, content, "utf-8");
|
|
6541
6664
|
}
|
|
6542
|
-
const bestPracticesPath =
|
|
6665
|
+
const bestPracticesPath = path5.join(cwd, ".bugzy/runtime/testing-best-practices.md");
|
|
6543
6666
|
if (!fs4.existsSync(bestPracticesPath)) {
|
|
6544
|
-
const templatePath =
|
|
6667
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/testing-best-practices.md");
|
|
6545
6668
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6546
6669
|
fs4.writeFileSync(bestPracticesPath, content, "utf-8");
|
|
6547
6670
|
}
|
|
6548
|
-
const testResultSchemaPath =
|
|
6671
|
+
const testResultSchemaPath = path5.join(cwd, ".bugzy/runtime/templates/test-result-schema.md");
|
|
6549
6672
|
if (!fs4.existsSync(testResultSchemaPath)) {
|
|
6550
|
-
const templatePath =
|
|
6673
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/templates/test-result-schema.md");
|
|
6551
6674
|
if (fs4.existsSync(templatePath)) {
|
|
6552
6675
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6553
6676
|
fs4.writeFileSync(testResultSchemaPath, content, "utf-8");
|
|
6554
6677
|
}
|
|
6555
6678
|
}
|
|
6556
|
-
const knowledgeBasePath =
|
|
6679
|
+
const knowledgeBasePath = path5.join(cwd, ".bugzy/runtime/knowledge-base.md");
|
|
6557
6680
|
if (!fs4.existsSync(knowledgeBasePath)) {
|
|
6558
|
-
const templatePath =
|
|
6681
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/knowledge-base.md");
|
|
6559
6682
|
if (fs4.existsSync(templatePath)) {
|
|
6560
6683
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6561
6684
|
fs4.writeFileSync(knowledgeBasePath, content, "utf-8");
|
|
6562
6685
|
}
|
|
6563
6686
|
}
|
|
6564
|
-
const knowledgeMaintenancePath =
|
|
6687
|
+
const knowledgeMaintenancePath = path5.join(cwd, ".bugzy/runtime/knowledge-maintenance-guide.md");
|
|
6565
6688
|
if (!fs4.existsSync(knowledgeMaintenancePath)) {
|
|
6566
|
-
const templatePath =
|
|
6689
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/knowledge-maintenance-guide.md");
|
|
6567
6690
|
if (fs4.existsSync(templatePath)) {
|
|
6568
6691
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6569
6692
|
fs4.writeFileSync(knowledgeMaintenancePath, content, "utf-8");
|
|
6570
6693
|
}
|
|
6571
6694
|
}
|
|
6572
|
-
const subagentMemoryPath =
|
|
6695
|
+
const subagentMemoryPath = path5.join(cwd, ".bugzy/runtime/subagent-memory-guide.md");
|
|
6573
6696
|
if (!fs4.existsSync(subagentMemoryPath)) {
|
|
6574
|
-
const templatePath =
|
|
6697
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/subagent-memory-guide.md");
|
|
6575
6698
|
if (fs4.existsSync(templatePath)) {
|
|
6576
6699
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6577
6700
|
fs4.writeFileSync(subagentMemoryPath, content, "utf-8");
|
|
6578
6701
|
}
|
|
6579
6702
|
}
|
|
6580
|
-
const testExecutionStrategyPath =
|
|
6703
|
+
const testExecutionStrategyPath = path5.join(cwd, ".bugzy/runtime/test-execution-strategy.md");
|
|
6581
6704
|
if (!fs4.existsSync(testExecutionStrategyPath)) {
|
|
6582
|
-
const templatePath =
|
|
6705
|
+
const templatePath = path5.join(templatesDir, ".bugzy/runtime/test-execution-strategy.md");
|
|
6583
6706
|
if (fs4.existsSync(templatePath)) {
|
|
6584
6707
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6585
6708
|
fs4.writeFileSync(testExecutionStrategyPath, content, "utf-8");
|
|
@@ -6589,18 +6712,28 @@ async function createRuntimeFiles() {
|
|
|
6589
6712
|
async function generateClaudeMd() {
|
|
6590
6713
|
const cwd = process.cwd();
|
|
6591
6714
|
const templatesDir = getTemplatesDir();
|
|
6592
|
-
const claudeMdPath =
|
|
6715
|
+
const claudeMdPath = path5.join(cwd, "CLAUDE.md");
|
|
6593
6716
|
if (!fs4.existsSync(claudeMdPath)) {
|
|
6594
|
-
const templatePath =
|
|
6717
|
+
const templatePath = path5.join(templatesDir, "CLAUDE.md");
|
|
6595
6718
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6596
6719
|
fs4.writeFileSync(claudeMdPath, content, "utf-8");
|
|
6597
6720
|
}
|
|
6598
6721
|
}
|
|
6722
|
+
async function generateAgentsMd() {
|
|
6723
|
+
const cwd = process.cwd();
|
|
6724
|
+
const templatesDir = getTemplatesDir();
|
|
6725
|
+
const agentsMdPath = path5.join(cwd, "AGENTS.md");
|
|
6726
|
+
if (!fs4.existsSync(agentsMdPath)) {
|
|
6727
|
+
const templatePath = path5.join(templatesDir, "AGENTS.md");
|
|
6728
|
+
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6729
|
+
fs4.writeFileSync(agentsMdPath, content, "utf-8");
|
|
6730
|
+
}
|
|
6731
|
+
}
|
|
6599
6732
|
async function updateGitignore() {
|
|
6600
6733
|
const cwd = process.cwd();
|
|
6601
|
-
const gitignorePath =
|
|
6734
|
+
const gitignorePath = path5.join(cwd, ".gitignore");
|
|
6602
6735
|
const templatesDir = getTemplatesDir();
|
|
6603
|
-
const templatePath =
|
|
6736
|
+
const templatePath = path5.join(templatesDir, ".gitignore-template");
|
|
6604
6737
|
const bugzyEntries = fs4.readFileSync(templatePath, "utf-8");
|
|
6605
6738
|
if (fs4.existsSync(gitignorePath)) {
|
|
6606
6739
|
const content = fs4.readFileSync(gitignorePath, "utf-8");
|
|
@@ -6615,7 +6748,7 @@ async function updateGitignore() {
|
|
|
6615
6748
|
// src/cli/generators/commands.ts
|
|
6616
6749
|
init_cjs_shims();
|
|
6617
6750
|
var fs5 = __toESM(require("fs"), 1);
|
|
6618
|
-
var
|
|
6751
|
+
var path6 = __toESM(require("path"), 1);
|
|
6619
6752
|
init_tasks();
|
|
6620
6753
|
|
|
6621
6754
|
// src/core/task-builder.ts
|
|
@@ -6665,22 +6798,80 @@ function buildTaskDefinition(taskSlug, projectSubAgents) {
|
|
|
6665
6798
|
};
|
|
6666
6799
|
}
|
|
6667
6800
|
|
|
6801
|
+
// src/core/tool-strings.ts
|
|
6802
|
+
init_cjs_shims();
|
|
6803
|
+
var TOOL_STRINGS = {
|
|
6804
|
+
"claude-code": {
|
|
6805
|
+
INVOKE_TEST_RUNNER: "Use the test-runner subagent to execute the tests",
|
|
6806
|
+
INVOKE_TEST_DEBUGGER_FIXER: "Use the test-debugger-fixer subagent to debug and fix the failing test",
|
|
6807
|
+
INVOKE_TEST_CODE_GENERATOR: "Use the test-code-generator subagent to generate automated test code",
|
|
6808
|
+
INVOKE_TEAM_COMMUNICATOR: "Use the team-communicator subagent to notify the team",
|
|
6809
|
+
INVOKE_ISSUE_TRACKER: "Use the issue-tracker subagent to create or update issues",
|
|
6810
|
+
INVOKE_DOCUMENTATION_RESEARCHER: "Use the documentation-researcher subagent to search and gather documentation"
|
|
6811
|
+
},
|
|
6812
|
+
"cursor": {
|
|
6813
|
+
INVOKE_TEST_RUNNER: 'Run the test-runner agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/test-runner.md)" --output-format text\n```',
|
|
6814
|
+
INVOKE_TEST_DEBUGGER_FIXER: 'Run the test-debugger-fixer agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/test-debugger-fixer.md)" --output-format text\n```',
|
|
6815
|
+
INVOKE_TEST_CODE_GENERATOR: 'Run the test-code-generator agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/test-code-generator.md)" --output-format text\n```',
|
|
6816
|
+
INVOKE_TEAM_COMMUNICATOR: 'Run the team-communicator agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/team-communicator.md)" --output-format text\n```',
|
|
6817
|
+
INVOKE_ISSUE_TRACKER: 'Run the issue-tracker agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/issue-tracker.md)" --output-format text\n```',
|
|
6818
|
+
INVOKE_DOCUMENTATION_RESEARCHER: 'Run the documentation-researcher agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/documentation-researcher.md)" --output-format text\n```'
|
|
6819
|
+
},
|
|
6820
|
+
"codex": {
|
|
6821
|
+
INVOKE_TEST_RUNNER: 'Run the test-runner agent:\n```bash\ncodex -p "$(cat .codex/agents/test-runner.md)"\n```',
|
|
6822
|
+
INVOKE_TEST_DEBUGGER_FIXER: 'Run the test-debugger-fixer agent:\n```bash\ncodex -p "$(cat .codex/agents/test-debugger-fixer.md)"\n```',
|
|
6823
|
+
INVOKE_TEST_CODE_GENERATOR: 'Run the test-code-generator agent:\n```bash\ncodex -p "$(cat .codex/agents/test-code-generator.md)"\n```',
|
|
6824
|
+
INVOKE_TEAM_COMMUNICATOR: 'Run the team-communicator agent:\n```bash\ncodex -p "$(cat .codex/agents/team-communicator.md)"\n```',
|
|
6825
|
+
INVOKE_ISSUE_TRACKER: 'Run the issue-tracker agent:\n```bash\ncodex -p "$(cat .codex/agents/issue-tracker.md)"\n```',
|
|
6826
|
+
INVOKE_DOCUMENTATION_RESEARCHER: 'Run the documentation-researcher agent:\n```bash\ncodex -p "$(cat .codex/agents/documentation-researcher.md)"\n```'
|
|
6827
|
+
}
|
|
6828
|
+
};
|
|
6829
|
+
function getToolString(toolId, key) {
|
|
6830
|
+
const toolStrings = TOOL_STRINGS[toolId];
|
|
6831
|
+
if (!toolStrings) {
|
|
6832
|
+
throw new Error(`Unknown tool: ${toolId}`);
|
|
6833
|
+
}
|
|
6834
|
+
const value = toolStrings[key];
|
|
6835
|
+
if (!value) {
|
|
6836
|
+
throw new Error(`Unknown string key: ${key} for tool: ${toolId}`);
|
|
6837
|
+
}
|
|
6838
|
+
return value;
|
|
6839
|
+
}
|
|
6840
|
+
function replaceInvocationPlaceholders(content, toolId) {
|
|
6841
|
+
let result = content;
|
|
6842
|
+
const keys = [
|
|
6843
|
+
"INVOKE_TEST_RUNNER",
|
|
6844
|
+
"INVOKE_TEST_DEBUGGER_FIXER",
|
|
6845
|
+
"INVOKE_TEST_CODE_GENERATOR",
|
|
6846
|
+
"INVOKE_TEAM_COMMUNICATOR",
|
|
6847
|
+
"INVOKE_ISSUE_TRACKER",
|
|
6848
|
+
"INVOKE_DOCUMENTATION_RESEARCHER"
|
|
6849
|
+
];
|
|
6850
|
+
for (const key of keys) {
|
|
6851
|
+
const placeholder = `{{${key}}}`;
|
|
6852
|
+
const replacement = getToolString(toolId, key);
|
|
6853
|
+
result = result.replace(new RegExp(placeholder, "g"), replacement);
|
|
6854
|
+
}
|
|
6855
|
+
return result;
|
|
6856
|
+
}
|
|
6857
|
+
|
|
6668
6858
|
// src/cli/generators/commands.ts
|
|
6669
6859
|
var COMMAND_FILTER = {
|
|
6670
6860
|
// Cloud-only commands (skip in local environment)
|
|
6671
6861
|
"handle-message": false,
|
|
6672
6862
|
"process-event": false
|
|
6673
6863
|
};
|
|
6674
|
-
async function generateCommands(subagents) {
|
|
6864
|
+
async function generateCommands(subagents, tool = DEFAULT_TOOL) {
|
|
6675
6865
|
const cwd = process.cwd();
|
|
6676
|
-
const
|
|
6866
|
+
const toolProfile = getToolProfile(tool);
|
|
6867
|
+
const commandsDir = path6.join(cwd, toolProfile.commandsDir);
|
|
6677
6868
|
if (!fs5.existsSync(commandsDir)) {
|
|
6678
6869
|
fs5.mkdirSync(commandsDir, { recursive: true });
|
|
6679
6870
|
}
|
|
6680
6871
|
const existingFiles = fs5.readdirSync(commandsDir);
|
|
6681
6872
|
for (const file of existingFiles) {
|
|
6682
6873
|
if (file.endsWith(".md")) {
|
|
6683
|
-
fs5.unlinkSync(
|
|
6874
|
+
fs5.unlinkSync(path6.join(commandsDir, file));
|
|
6684
6875
|
}
|
|
6685
6876
|
}
|
|
6686
6877
|
const projectSubAgents = Object.entries(subagents).map(
|
|
@@ -6694,18 +6885,35 @@ async function generateCommands(subagents) {
|
|
|
6694
6885
|
const outputSlug = typeof filterValue === "string" ? filterValue : slug;
|
|
6695
6886
|
try {
|
|
6696
6887
|
const taskDef = buildTaskDefinition(slug, projectSubAgents);
|
|
6697
|
-
const
|
|
6698
|
-
const
|
|
6888
|
+
const processedContent = replaceInvocationPlaceholders(taskDef.content, tool);
|
|
6889
|
+
const content = formatCommandMarkdown(taskDef.frontmatter, processedContent, toolProfile.commandFrontmatter);
|
|
6890
|
+
const fileName = `${outputSlug}${toolProfile.commandExtension}`;
|
|
6891
|
+
const filePath = path6.join(commandsDir, fileName);
|
|
6699
6892
|
fs5.writeFileSync(filePath, content, "utf-8");
|
|
6700
6893
|
} catch (error) {
|
|
6701
|
-
const
|
|
6702
|
-
const
|
|
6894
|
+
const processedContent = replaceInvocationPlaceholders(template.baseContent, tool);
|
|
6895
|
+
const content = formatCommandMarkdown(template.frontmatter, processedContent, toolProfile.commandFrontmatter);
|
|
6896
|
+
const fileName = `${outputSlug}${toolProfile.commandExtension}`;
|
|
6897
|
+
const filePath = path6.join(commandsDir, fileName);
|
|
6703
6898
|
fs5.writeFileSync(filePath, content, "utf-8");
|
|
6704
6899
|
console.warn(`Warning: Generated ${outputSlug} without required subagents: ${error.message}`);
|
|
6705
6900
|
}
|
|
6706
6901
|
}
|
|
6707
6902
|
}
|
|
6708
|
-
function formatCommandMarkdown(frontmatter, content) {
|
|
6903
|
+
function formatCommandMarkdown(frontmatter, content, includeFrontmatter) {
|
|
6904
|
+
if (!includeFrontmatter) {
|
|
6905
|
+
const lines2 = [];
|
|
6906
|
+
if (frontmatter.description) {
|
|
6907
|
+
lines2.push(`# ${frontmatter.description}`);
|
|
6908
|
+
lines2.push("");
|
|
6909
|
+
}
|
|
6910
|
+
if (frontmatter["argument-hint"]) {
|
|
6911
|
+
lines2.push(`**Arguments**: ${frontmatter["argument-hint"]}`);
|
|
6912
|
+
lines2.push("");
|
|
6913
|
+
}
|
|
6914
|
+
lines2.push(content);
|
|
6915
|
+
return lines2.join("\n");
|
|
6916
|
+
}
|
|
6709
6917
|
const lines = ["---"];
|
|
6710
6918
|
for (const [key, value] of Object.entries(frontmatter)) {
|
|
6711
6919
|
if (value !== void 0 && value !== null) {
|
|
@@ -6722,17 +6930,18 @@ function formatCommandMarkdown(frontmatter, content) {
|
|
|
6722
6930
|
// src/cli/generators/agents.ts
|
|
6723
6931
|
init_cjs_shims();
|
|
6724
6932
|
var fs6 = __toESM(require("fs"), 1);
|
|
6725
|
-
var
|
|
6726
|
-
async function generateAgents(subagents) {
|
|
6933
|
+
var path7 = __toESM(require("path"), 1);
|
|
6934
|
+
async function generateAgents(subagents, tool = DEFAULT_TOOL) {
|
|
6727
6935
|
const cwd = process.cwd();
|
|
6728
|
-
const
|
|
6936
|
+
const toolProfile = getToolProfile(tool);
|
|
6937
|
+
const agentsDir = path7.join(cwd, toolProfile.agentsDir);
|
|
6729
6938
|
if (!fs6.existsSync(agentsDir)) {
|
|
6730
6939
|
fs6.mkdirSync(agentsDir, { recursive: true });
|
|
6731
6940
|
}
|
|
6732
6941
|
const existingFiles = fs6.readdirSync(agentsDir);
|
|
6733
6942
|
for (const file of existingFiles) {
|
|
6734
6943
|
if (file.endsWith(".md")) {
|
|
6735
|
-
fs6.unlinkSync(
|
|
6944
|
+
fs6.unlinkSync(path7.join(agentsDir, file));
|
|
6736
6945
|
}
|
|
6737
6946
|
}
|
|
6738
6947
|
for (const [role, integration] of Object.entries(subagents)) {
|
|
@@ -6741,12 +6950,16 @@ async function generateAgents(subagents) {
|
|
|
6741
6950
|
console.warn(`Warning: Could not load template for ${role} with ${integration}`);
|
|
6742
6951
|
continue;
|
|
6743
6952
|
}
|
|
6744
|
-
const content = formatAgentMarkdown(config.frontmatter, config.content);
|
|
6745
|
-
const
|
|
6953
|
+
const content = formatAgentMarkdown(config.frontmatter, config.content, toolProfile.agentFrontmatter);
|
|
6954
|
+
const fileName = `${role}${toolProfile.agentExtension}`;
|
|
6955
|
+
const filePath = path7.join(agentsDir, fileName);
|
|
6746
6956
|
fs6.writeFileSync(filePath, content, "utf-8");
|
|
6747
6957
|
}
|
|
6748
6958
|
}
|
|
6749
|
-
function formatAgentMarkdown(frontmatter, content) {
|
|
6959
|
+
function formatAgentMarkdown(frontmatter, content, includeFrontmatter) {
|
|
6960
|
+
if (!includeFrontmatter) {
|
|
6961
|
+
return content;
|
|
6962
|
+
}
|
|
6750
6963
|
const lines = ["---"];
|
|
6751
6964
|
for (const [key, value] of Object.entries(frontmatter)) {
|
|
6752
6965
|
if (value !== void 0 && value !== null) {
|
|
@@ -6767,7 +6980,8 @@ function formatAgentMarkdown(frontmatter, content) {
|
|
|
6767
6980
|
// src/cli/generators/mcp.ts
|
|
6768
6981
|
init_cjs_shims();
|
|
6769
6982
|
var fs7 = __toESM(require("fs"), 1);
|
|
6770
|
-
var
|
|
6983
|
+
var path8 = __toESM(require("path"), 1);
|
|
6984
|
+
var import_child_process2 = require("child_process");
|
|
6771
6985
|
|
|
6772
6986
|
// src/mcp/index.ts
|
|
6773
6987
|
init_cjs_shims();
|
|
@@ -6777,6 +6991,7 @@ var MCP_SERVERS = {
|
|
|
6777
6991
|
name: "Slack",
|
|
6778
6992
|
description: "Slack MCP server for messaging and channel operations",
|
|
6779
6993
|
requiresCredentials: true,
|
|
6994
|
+
npmPackages: ["simple-slack-mcp-server"],
|
|
6780
6995
|
config: {
|
|
6781
6996
|
command: "slack-mcp-server",
|
|
6782
6997
|
args: [],
|
|
@@ -6790,6 +7005,7 @@ var MCP_SERVERS = {
|
|
|
6790
7005
|
name: "Microsoft Teams",
|
|
6791
7006
|
description: "Microsoft Teams MCP server for messaging and channel operations",
|
|
6792
7007
|
requiresCredentials: true,
|
|
7008
|
+
npmPackages: ["@bugzy-ai/teams-mcp-server"],
|
|
6793
7009
|
config: {
|
|
6794
7010
|
command: "teams-mcp-server",
|
|
6795
7011
|
args: [],
|
|
@@ -6803,6 +7019,7 @@ var MCP_SERVERS = {
|
|
|
6803
7019
|
name: "Playwright",
|
|
6804
7020
|
description: "Playwright MCP server for browser automation",
|
|
6805
7021
|
requiresCredentials: false,
|
|
7022
|
+
npmPackages: ["@playwright/mcp"],
|
|
6806
7023
|
config: {
|
|
6807
7024
|
command: "mcp-server-playwright",
|
|
6808
7025
|
args: [
|
|
@@ -6827,6 +7044,7 @@ var MCP_SERVERS = {
|
|
|
6827
7044
|
name: "Notion",
|
|
6828
7045
|
description: "Notion MCP server for documentation",
|
|
6829
7046
|
requiresCredentials: true,
|
|
7047
|
+
npmPackages: ["@notionhq/notion-mcp-server"],
|
|
6830
7048
|
config: {
|
|
6831
7049
|
command: "notion-mcp-server",
|
|
6832
7050
|
args: [],
|
|
@@ -6840,6 +7058,7 @@ var MCP_SERVERS = {
|
|
|
6840
7058
|
name: "Jira Server (On-Prem)",
|
|
6841
7059
|
description: "Jira Server MCP via tunnel for on-premise instances",
|
|
6842
7060
|
requiresCredentials: true,
|
|
7061
|
+
npmPackages: ["@mcp-tunnel/wrapper", "@bugzy-ai/jira-mcp-server"],
|
|
6843
7062
|
config: {
|
|
6844
7063
|
command: "mcp-tunnel",
|
|
6845
7064
|
args: ["--server", "jira-mcp-server"],
|
|
@@ -6936,12 +7155,59 @@ function buildMCPConfig(requiredServers, target = "container") {
|
|
|
6936
7155
|
}
|
|
6937
7156
|
|
|
6938
7157
|
// src/cli/generators/mcp.ts
|
|
6939
|
-
async function generateMCPConfig(mcpServers) {
|
|
7158
|
+
async function generateMCPConfig(mcpServers, tool = DEFAULT_TOOL) {
|
|
6940
7159
|
const cwd = process.cwd();
|
|
6941
|
-
const
|
|
6942
|
-
|
|
6943
|
-
|
|
6944
|
-
|
|
7160
|
+
const toolProfile = getToolProfile(tool);
|
|
7161
|
+
if (toolProfile.mcpFormat === "json") {
|
|
7162
|
+
const mcpConfigPath = path8.join(cwd, toolProfile.mcpConfigPath);
|
|
7163
|
+
const mcpDir = path8.dirname(mcpConfigPath);
|
|
7164
|
+
if (!fs7.existsSync(mcpDir)) {
|
|
7165
|
+
fs7.mkdirSync(mcpDir, { recursive: true });
|
|
7166
|
+
}
|
|
7167
|
+
const mcpConfig = buildMCPConfig(mcpServers, "local");
|
|
7168
|
+
const content = JSON.stringify(mcpConfig, null, 2);
|
|
7169
|
+
fs7.writeFileSync(mcpConfigPath, content, "utf-8");
|
|
7170
|
+
} else if (toolProfile.mcpFormat === "toml") {
|
|
7171
|
+
return;
|
|
7172
|
+
}
|
|
7173
|
+
}
|
|
7174
|
+
function buildCodexMCPCommand(serverName) {
|
|
7175
|
+
const serverTemplate = MCP_SERVERS[serverName];
|
|
7176
|
+
if (!serverTemplate) {
|
|
7177
|
+
throw new Error(`Unknown MCP server: ${serverName}`);
|
|
7178
|
+
}
|
|
7179
|
+
const args = ["mcp", "add", `bugzy-${serverName}`];
|
|
7180
|
+
const envVars = [];
|
|
7181
|
+
if (serverTemplate.config.env) {
|
|
7182
|
+
for (const [key, value] of Object.entries(serverTemplate.config.env)) {
|
|
7183
|
+
const match = value.match(/\$\{([A-Z_]+)\}/);
|
|
7184
|
+
if (match) {
|
|
7185
|
+
args.push("--env", `${key}=$${match[1]}`);
|
|
7186
|
+
envVars.push(match[1]);
|
|
7187
|
+
}
|
|
7188
|
+
}
|
|
7189
|
+
}
|
|
7190
|
+
args.push("--", serverTemplate.config.command);
|
|
7191
|
+
if (serverTemplate.config.args?.length) {
|
|
7192
|
+
args.push(...serverTemplate.config.args);
|
|
7193
|
+
}
|
|
7194
|
+
return { args, envVars };
|
|
7195
|
+
}
|
|
7196
|
+
async function getConfiguredCodexMCPServers() {
|
|
7197
|
+
try {
|
|
7198
|
+
const output = (0, import_child_process2.execSync)("codex mcp list", {
|
|
7199
|
+
encoding: "utf-8",
|
|
7200
|
+
env: { ...process.env, CODEX_HOME: path8.join(process.cwd(), ".codex") },
|
|
7201
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7202
|
+
});
|
|
7203
|
+
const lines = output.split("\n");
|
|
7204
|
+
return lines.filter((line) => line.includes("bugzy-")).map((line) => {
|
|
7205
|
+
const match = line.match(/bugzy-([a-z-]+)/);
|
|
7206
|
+
return match ? match[1] : null;
|
|
7207
|
+
}).filter((name) => name !== null);
|
|
7208
|
+
} catch {
|
|
7209
|
+
return [];
|
|
7210
|
+
}
|
|
6945
7211
|
}
|
|
6946
7212
|
function getMCPServersFromSubagents(subagents) {
|
|
6947
7213
|
const mcps = /* @__PURE__ */ new Set();
|
|
@@ -6951,13 +7217,16 @@ function getMCPServersFromSubagents(subagents) {
|
|
|
6951
7217
|
return Array.from(mcps);
|
|
6952
7218
|
}
|
|
6953
7219
|
|
|
7220
|
+
// src/cli/commands/setup.ts
|
|
7221
|
+
var import_child_process4 = require("child_process");
|
|
7222
|
+
|
|
6954
7223
|
// src/cli/generators/env.ts
|
|
6955
7224
|
init_cjs_shims();
|
|
6956
7225
|
var fs8 = __toESM(require("fs"), 1);
|
|
6957
|
-
var
|
|
7226
|
+
var path9 = __toESM(require("path"), 1);
|
|
6958
7227
|
async function generateEnvExample(mcpServers) {
|
|
6959
7228
|
const cwd = process.cwd();
|
|
6960
|
-
const envExamplePath =
|
|
7229
|
+
const envExamplePath = path9.join(cwd, ".env.example");
|
|
6961
7230
|
const header = `# ============================================
|
|
6962
7231
|
# Bugzy OSS - Environment Variables
|
|
6963
7232
|
# ============================================
|
|
@@ -6983,11 +7252,13 @@ function getMCPEnvConfig(serverName) {
|
|
|
6983
7252
|
const configs = {
|
|
6984
7253
|
slack: `
|
|
6985
7254
|
# Slack MCP Server
|
|
6986
|
-
#
|
|
7255
|
+
# Setup guide: https://github.com/bugzy-ai/bugzy/blob/main/docs/slack-setup.md
|
|
7256
|
+
# Required scopes: channels:read, chat:write, chat:write.public, reactions:write
|
|
6987
7257
|
SLACK_ACCESS_TOKEN=`,
|
|
6988
7258
|
notion: `
|
|
6989
7259
|
# Notion MCP Server
|
|
6990
|
-
#
|
|
7260
|
+
# Setup guide: https://github.com/bugzy-ai/bugzy/blob/main/docs/notion-setup.md
|
|
7261
|
+
# Requires: Internal Integration Token (ntn_* or secret_*)
|
|
6991
7262
|
NOTION_TOKEN=`,
|
|
6992
7263
|
linear: `
|
|
6993
7264
|
# Linear MCP Server
|
|
@@ -7017,8 +7288,8 @@ GITHUB_TOKEN=`
|
|
|
7017
7288
|
// src/cli/generators/scaffold-playwright.ts
|
|
7018
7289
|
init_cjs_shims();
|
|
7019
7290
|
var fs9 = __toESM(require("fs"), 1);
|
|
7020
|
-
var
|
|
7021
|
-
var
|
|
7291
|
+
var path10 = __toESM(require("path"), 1);
|
|
7292
|
+
var import_child_process3 = require("child_process");
|
|
7022
7293
|
async function scaffoldPlaywrightProject(options) {
|
|
7023
7294
|
const { projectName, targetDir, skipInstall = false } = options;
|
|
7024
7295
|
console.log("\n\u{1F3AD} Scaffolding Playwright test automation project...\n");
|
|
@@ -7051,7 +7322,7 @@ async function createDirectoryStructure(targetDir) {
|
|
|
7051
7322
|
"test-runs"
|
|
7052
7323
|
];
|
|
7053
7324
|
for (const dir of directories) {
|
|
7054
|
-
const fullPath =
|
|
7325
|
+
const fullPath = path10.join(targetDir, dir);
|
|
7055
7326
|
if (!fs9.existsSync(fullPath)) {
|
|
7056
7327
|
fs9.mkdirSync(fullPath, { recursive: true });
|
|
7057
7328
|
console.log(` \u2713 Created ${dir}/`);
|
|
@@ -7060,11 +7331,11 @@ async function createDirectoryStructure(targetDir) {
|
|
|
7060
7331
|
}
|
|
7061
7332
|
async function copyTemplateFiles(targetDir, projectName) {
|
|
7062
7333
|
const possiblePaths = [
|
|
7063
|
-
|
|
7334
|
+
path10.join(__dirname, "../../templates/playwright"),
|
|
7064
7335
|
// When running from dist
|
|
7065
|
-
|
|
7336
|
+
path10.join(process.cwd(), "templates/playwright"),
|
|
7066
7337
|
// When running from project root
|
|
7067
|
-
|
|
7338
|
+
path10.join(__dirname, "../../../templates/playwright")
|
|
7068
7339
|
// When running tests
|
|
7069
7340
|
];
|
|
7070
7341
|
let templatesDir = "";
|
|
@@ -7077,9 +7348,9 @@ async function copyTemplateFiles(targetDir, projectName) {
|
|
|
7077
7348
|
if (!templatesDir) {
|
|
7078
7349
|
throw new Error("Templates directory not found. Searched paths: " + possiblePaths.join(", "));
|
|
7079
7350
|
}
|
|
7080
|
-
const initTemplatesDir =
|
|
7081
|
-
const testRunsReadmeSrc =
|
|
7082
|
-
const testRunsReadmeDest =
|
|
7351
|
+
const initTemplatesDir = path10.join(__dirname, "../../templates/init");
|
|
7352
|
+
const testRunsReadmeSrc = path10.join(initTemplatesDir, "test-runs/README.md");
|
|
7353
|
+
const testRunsReadmeDest = path10.join(targetDir, "test-runs/README.md");
|
|
7083
7354
|
if (fs9.existsSync(testRunsReadmeSrc)) {
|
|
7084
7355
|
const content = fs9.readFileSync(testRunsReadmeSrc, "utf-8");
|
|
7085
7356
|
fs9.writeFileSync(testRunsReadmeDest, content, "utf-8");
|
|
@@ -7123,8 +7394,8 @@ async function copyTemplateFiles(targetDir, projectName) {
|
|
|
7123
7394
|
}
|
|
7124
7395
|
];
|
|
7125
7396
|
for (const template of templates) {
|
|
7126
|
-
const srcPath =
|
|
7127
|
-
const destPath =
|
|
7397
|
+
const srcPath = path10.join(templatesDir, template.src);
|
|
7398
|
+
const destPath = path10.join(targetDir, template.dest);
|
|
7128
7399
|
if (fs9.existsSync(srcPath)) {
|
|
7129
7400
|
let content = fs9.readFileSync(srcPath, "utf-8");
|
|
7130
7401
|
if (template.process) {
|
|
@@ -7134,7 +7405,7 @@ async function copyTemplateFiles(targetDir, projectName) {
|
|
|
7134
7405
|
DATE: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
|
|
7135
7406
|
});
|
|
7136
7407
|
}
|
|
7137
|
-
const destDir =
|
|
7408
|
+
const destDir = path10.dirname(destPath);
|
|
7138
7409
|
if (!fs9.existsSync(destDir)) {
|
|
7139
7410
|
fs9.mkdirSync(destDir, { recursive: true });
|
|
7140
7411
|
}
|
|
@@ -7154,7 +7425,7 @@ function processTemplate(content, values) {
|
|
|
7154
7425
|
return processed;
|
|
7155
7426
|
}
|
|
7156
7427
|
async function updateGitignore2(targetDir) {
|
|
7157
|
-
const gitignorePath =
|
|
7428
|
+
const gitignorePath = path10.join(targetDir, ".gitignore");
|
|
7158
7429
|
const playwrightEntries = `
|
|
7159
7430
|
# Playwright
|
|
7160
7431
|
test-results/
|
|
@@ -7174,7 +7445,7 @@ tests/.auth/
|
|
|
7174
7445
|
}
|
|
7175
7446
|
}
|
|
7176
7447
|
async function createPackageJson(targetDir, projectName) {
|
|
7177
|
-
const packageJsonPath =
|
|
7448
|
+
const packageJsonPath = path10.join(targetDir, "package.json");
|
|
7178
7449
|
const recommendedDeps = {
|
|
7179
7450
|
"@playwright/test": "^1.48.0",
|
|
7180
7451
|
"@types/node": "^20.0.0",
|
|
@@ -7230,7 +7501,7 @@ async function installDependencies(targetDir) {
|
|
|
7230
7501
|
console.log(`
|
|
7231
7502
|
\u{1F4E6} Installing dependencies using ${packageManager}...`);
|
|
7232
7503
|
const installCommand = packageManager === "pnpm" ? "pnpm install" : packageManager === "yarn" ? "yarn install" : "npm install";
|
|
7233
|
-
(0,
|
|
7504
|
+
(0, import_child_process3.execSync)(installCommand, {
|
|
7234
7505
|
cwd: targetDir,
|
|
7235
7506
|
stdio: "inherit"
|
|
7236
7507
|
});
|
|
@@ -7241,17 +7512,17 @@ async function installDependencies(targetDir) {
|
|
|
7241
7512
|
}
|
|
7242
7513
|
}
|
|
7243
7514
|
function detectPackageManager(targetDir) {
|
|
7244
|
-
if (fs9.existsSync(
|
|
7515
|
+
if (fs9.existsSync(path10.join(targetDir, "pnpm-lock.yaml"))) {
|
|
7245
7516
|
return "pnpm";
|
|
7246
7517
|
}
|
|
7247
|
-
if (fs9.existsSync(
|
|
7518
|
+
if (fs9.existsSync(path10.join(targetDir, "yarn.lock"))) {
|
|
7248
7519
|
return "yarn";
|
|
7249
7520
|
}
|
|
7250
7521
|
return "npm";
|
|
7251
7522
|
}
|
|
7252
7523
|
function isPlaywrightScaffolded(targetDir) {
|
|
7253
|
-
const playwrightConfig =
|
|
7254
|
-
const testsDir =
|
|
7524
|
+
const playwrightConfig = path10.join(targetDir, "playwright.config.ts");
|
|
7525
|
+
const testsDir = path10.join(targetDir, "tests");
|
|
7255
7526
|
return fs9.existsSync(playwrightConfig) && fs9.existsSync(testsDir);
|
|
7256
7527
|
}
|
|
7257
7528
|
|
|
@@ -7295,9 +7566,26 @@ async function setupProject(cliArgs = []) {
|
|
|
7295
7566
|
async function firstTimeSetup(cliSubagents) {
|
|
7296
7567
|
console.log(getBanner());
|
|
7297
7568
|
console.log(import_chalk2.default.cyan(" Project Setup\n"));
|
|
7569
|
+
const toolOptions = getToolOptions();
|
|
7570
|
+
const { selectedTool } = await import_inquirer.default.prompt([{
|
|
7571
|
+
type: "list",
|
|
7572
|
+
name: "selectedTool",
|
|
7573
|
+
message: "Which AI coding assistant do you use?",
|
|
7574
|
+
choices: toolOptions.map((opt) => ({
|
|
7575
|
+
name: opt.hint ? `${opt.label} - ${import_chalk2.default.gray(opt.hint)}` : opt.label,
|
|
7576
|
+
value: opt.value
|
|
7577
|
+
})),
|
|
7578
|
+
default: DEFAULT_TOOL
|
|
7579
|
+
}]);
|
|
7580
|
+
const tool = selectedTool;
|
|
7581
|
+
const toolProfile = getToolProfile(tool);
|
|
7582
|
+
console.log(import_chalk2.default.gray(`
|
|
7583
|
+
\u2713 Using ${toolProfile.name}
|
|
7584
|
+
`));
|
|
7298
7585
|
let spinner = (0, import_ora2.default)("Creating project structure").start();
|
|
7299
|
-
await createProjectStructure();
|
|
7300
|
-
|
|
7586
|
+
await createProjectStructure(tool);
|
|
7587
|
+
const toolDirName = path11.dirname(toolProfile.commandsDir);
|
|
7588
|
+
spinner.succeed(import_chalk2.default.green(`Created .bugzy/ and ${toolDirName}/ directories`));
|
|
7301
7589
|
const subagents = {};
|
|
7302
7590
|
if (cliSubagents) {
|
|
7303
7591
|
console.log(import_chalk2.default.cyan("\nConfiguring subagents from CLI arguments:\n"));
|
|
@@ -7354,16 +7642,48 @@ async function firstTimeSetup(cliSubagents) {
|
|
|
7354
7642
|
}
|
|
7355
7643
|
}
|
|
7356
7644
|
}
|
|
7645
|
+
const mcpServers = getMCPServersFromSubagents(subagents);
|
|
7646
|
+
const packagesToInstall = [...new Set(
|
|
7647
|
+
mcpServers.flatMap((s) => MCP_SERVERS[s]?.npmPackages ?? [])
|
|
7648
|
+
)];
|
|
7649
|
+
if (packagesToInstall.length > 0) {
|
|
7650
|
+
console.log(import_chalk2.default.cyan("\nMCP Server Packages Required:\n"));
|
|
7651
|
+
packagesToInstall.forEach((pkg) => console.log(import_chalk2.default.white(` \u2022 ${pkg}`)));
|
|
7652
|
+
const { installMCP } = await import_inquirer.default.prompt([{
|
|
7653
|
+
type: "confirm",
|
|
7654
|
+
name: "installMCP",
|
|
7655
|
+
message: "Install MCP packages globally now?",
|
|
7656
|
+
default: true
|
|
7657
|
+
}]);
|
|
7658
|
+
if (installMCP) {
|
|
7659
|
+
const spinner2 = (0, import_ora2.default)("Installing MCP packages").start();
|
|
7660
|
+
try {
|
|
7661
|
+
(0, import_child_process4.execSync)(`npm install -g ${packagesToInstall.join(" ")}`, { stdio: "pipe" });
|
|
7662
|
+
spinner2.succeed(import_chalk2.default.green("MCP packages installed"));
|
|
7663
|
+
} catch (e) {
|
|
7664
|
+
spinner2.fail(import_chalk2.default.red("Some packages failed to install"));
|
|
7665
|
+
console.log(import_chalk2.default.yellow("\nInstall manually: npm install -g " + packagesToInstall.join(" ")));
|
|
7666
|
+
}
|
|
7667
|
+
} else {
|
|
7668
|
+
console.log(import_chalk2.default.yellow("\n\u26A0\uFE0F MCP servers will not work until packages are installed:"));
|
|
7669
|
+
console.log(import_chalk2.default.white(` npm install -g ${packagesToInstall.join(" ")}
|
|
7670
|
+
`));
|
|
7671
|
+
}
|
|
7672
|
+
}
|
|
7357
7673
|
spinner = (0, import_ora2.default)("Saving configuration").start();
|
|
7358
|
-
const projectName =
|
|
7359
|
-
const config = createDefaultConfig(projectName);
|
|
7674
|
+
const projectName = path11.basename(process.cwd());
|
|
7675
|
+
const config = createDefaultConfig(projectName, tool);
|
|
7360
7676
|
config.subagents = subagents;
|
|
7361
7677
|
saveConfig(config);
|
|
7362
7678
|
spinner.succeed(import_chalk2.default.green("Saved to .bugzy/config.json"));
|
|
7363
|
-
await regenerateAll(subagents);
|
|
7364
|
-
spinner = (0, import_ora2.default)(
|
|
7365
|
-
|
|
7366
|
-
|
|
7679
|
+
await regenerateAll(subagents, tool);
|
|
7680
|
+
spinner = (0, import_ora2.default)(`Creating ${toolProfile.memoryFile}`).start();
|
|
7681
|
+
if (tool === "claude-code") {
|
|
7682
|
+
await generateClaudeMd();
|
|
7683
|
+
} else {
|
|
7684
|
+
await generateAgentsMd();
|
|
7685
|
+
}
|
|
7686
|
+
spinner.succeed(import_chalk2.default.green(`Created ${toolProfile.memoryFile}`));
|
|
7367
7687
|
spinner = (0, import_ora2.default)("Updating .gitignore").start();
|
|
7368
7688
|
await updateGitignore();
|
|
7369
7689
|
spinner.succeed(import_chalk2.default.green("Updated .gitignore"));
|
|
@@ -7375,11 +7695,23 @@ async function firstTimeSetup(cliSubagents) {
|
|
|
7375
7695
|
});
|
|
7376
7696
|
}
|
|
7377
7697
|
console.log(import_chalk2.default.green.bold("\n\u2705 Setup complete!\n"));
|
|
7698
|
+
console.log(import_chalk2.default.cyan("\u{1F4CB} Project Context:"));
|
|
7699
|
+
console.log(import_chalk2.default.white(" Edit .bugzy/runtime/project-context.md to help the AI understand your project:"));
|
|
7700
|
+
console.log(import_chalk2.default.gray(" \u2022 Project description and tech stack"));
|
|
7701
|
+
console.log(import_chalk2.default.gray(" \u2022 Team communication channels"));
|
|
7702
|
+
console.log(import_chalk2.default.gray(" \u2022 Bug tracking workflow"));
|
|
7703
|
+
console.log(import_chalk2.default.gray(" \u2022 Testing conventions\n"));
|
|
7378
7704
|
console.log(import_chalk2.default.yellow("Next steps:"));
|
|
7379
7705
|
console.log(import_chalk2.default.white("1. cp .env.example .env"));
|
|
7380
7706
|
console.log(import_chalk2.default.white("2. Edit .env and add your API tokens"));
|
|
7381
|
-
|
|
7382
|
-
|
|
7707
|
+
if (subagents["test-runner"]) {
|
|
7708
|
+
console.log(import_chalk2.default.white("3. npx playwright install (install browser binaries)"));
|
|
7709
|
+
console.log(import_chalk2.default.white("4. Edit .bugzy/runtime/project-context.md"));
|
|
7710
|
+
console.log(import_chalk2.default.white("5. Run:"), import_chalk2.default.cyan("bugzy"));
|
|
7711
|
+
} else {
|
|
7712
|
+
console.log(import_chalk2.default.white("3. Edit .bugzy/runtime/project-context.md"));
|
|
7713
|
+
console.log(import_chalk2.default.white("4. Run:"), import_chalk2.default.cyan("bugzy"));
|
|
7714
|
+
}
|
|
7383
7715
|
console.log();
|
|
7384
7716
|
}
|
|
7385
7717
|
async function reconfigureProject() {
|
|
@@ -7390,11 +7722,38 @@ async function reconfigureProject() {
|
|
|
7390
7722
|
console.error(import_chalk2.default.red("Error: Could not load existing configuration"));
|
|
7391
7723
|
process.exit(1);
|
|
7392
7724
|
}
|
|
7725
|
+
const currentTool = getToolFromConfig(existingConfig);
|
|
7726
|
+
const currentToolProfile = getToolProfile(currentTool);
|
|
7393
7727
|
console.log(import_chalk2.default.gray("Current configuration:"));
|
|
7728
|
+
console.log(import_chalk2.default.gray(` Tool: ${currentToolProfile.name}`));
|
|
7394
7729
|
for (const [role, integration] of Object.entries(existingConfig.subagents)) {
|
|
7395
7730
|
console.log(import_chalk2.default.gray(` \u2022 ${role}: ${integration}`));
|
|
7396
7731
|
}
|
|
7397
7732
|
console.log();
|
|
7733
|
+
const toolOptions = getToolOptions();
|
|
7734
|
+
const { changeTool } = await import_inquirer.default.prompt([{
|
|
7735
|
+
type: "confirm",
|
|
7736
|
+
name: "changeTool",
|
|
7737
|
+
message: `Keep using ${currentToolProfile.name}?`,
|
|
7738
|
+
default: true
|
|
7739
|
+
}]);
|
|
7740
|
+
let tool = currentTool;
|
|
7741
|
+
if (!changeTool) {
|
|
7742
|
+
const { selectedTool } = await import_inquirer.default.prompt([{
|
|
7743
|
+
type: "list",
|
|
7744
|
+
name: "selectedTool",
|
|
7745
|
+
message: "Which AI coding assistant do you want to use?",
|
|
7746
|
+
choices: toolOptions.map((opt) => ({
|
|
7747
|
+
name: opt.hint ? `${opt.label} - ${import_chalk2.default.gray(opt.hint)}` : opt.label,
|
|
7748
|
+
value: opt.value
|
|
7749
|
+
})),
|
|
7750
|
+
default: currentTool
|
|
7751
|
+
}]);
|
|
7752
|
+
tool = selectedTool;
|
|
7753
|
+
console.log(import_chalk2.default.gray(`
|
|
7754
|
+
\u2713 Switching to ${getToolProfile(tool).name}
|
|
7755
|
+
`));
|
|
7756
|
+
}
|
|
7398
7757
|
const allSubAgents = getAllSubAgents();
|
|
7399
7758
|
const newSubagents = {};
|
|
7400
7759
|
for (const subagent of allSubAgents) {
|
|
@@ -7470,13 +7829,19 @@ async function reconfigureProject() {
|
|
|
7470
7829
|
}
|
|
7471
7830
|
}
|
|
7472
7831
|
let spinner = (0, import_ora2.default)("Updating configuration").start();
|
|
7832
|
+
existingConfig.tool = tool;
|
|
7473
7833
|
existingConfig.subagents = newSubagents;
|
|
7474
7834
|
await saveConfig(existingConfig);
|
|
7475
7835
|
spinner.succeed(import_chalk2.default.green("Updated .bugzy/config.json"));
|
|
7476
|
-
await regenerateAll(newSubagents);
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
7836
|
+
await regenerateAll(newSubagents, tool);
|
|
7837
|
+
const toolProfile = getToolProfile(tool);
|
|
7838
|
+
spinner = (0, import_ora2.default)(`Creating ${toolProfile.memoryFile}`).start();
|
|
7839
|
+
if (tool === "claude-code") {
|
|
7840
|
+
await generateClaudeMd();
|
|
7841
|
+
} else {
|
|
7842
|
+
await generateAgentsMd();
|
|
7843
|
+
}
|
|
7844
|
+
spinner.succeed(import_chalk2.default.green(`Created ${toolProfile.memoryFile}`));
|
|
7480
7845
|
console.log(import_chalk2.default.green.bold("\n\u2705 Reconfiguration complete!\n"));
|
|
7481
7846
|
console.log(import_chalk2.default.yellow("Next steps:"));
|
|
7482
7847
|
console.log(import_chalk2.default.white("1. Check .env.example for new required secrets"));
|
|
@@ -7484,23 +7849,52 @@ async function reconfigureProject() {
|
|
|
7484
7849
|
console.log(import_chalk2.default.white("3. Run:"), import_chalk2.default.cyan("bugzy"));
|
|
7485
7850
|
console.log();
|
|
7486
7851
|
}
|
|
7487
|
-
async function regenerateAll(subagents) {
|
|
7852
|
+
async function regenerateAll(subagents, tool = DEFAULT_TOOL) {
|
|
7853
|
+
const toolProfile = getToolProfile(tool);
|
|
7488
7854
|
let spinner = (0, import_ora2.default)("Generating task commands").start();
|
|
7489
|
-
await generateCommands(subagents);
|
|
7855
|
+
await generateCommands(subagents, tool);
|
|
7490
7856
|
const taskCount = Object.keys((init_tasks(), __toCommonJS(tasks_exports)).TASK_TEMPLATES).length;
|
|
7491
|
-
spinner.succeed(import_chalk2.default.green(`Generated ${taskCount} task commands in .
|
|
7857
|
+
spinner.succeed(import_chalk2.default.green(`Generated ${taskCount} task commands in ${toolProfile.commandsDir}/`));
|
|
7492
7858
|
spinner = (0, import_ora2.default)("Generating subagent configurations").start();
|
|
7493
|
-
await generateAgents(subagents);
|
|
7859
|
+
await generateAgents(subagents, tool);
|
|
7494
7860
|
const subagentCount = Object.keys(subagents).length;
|
|
7495
|
-
spinner.succeed(import_chalk2.default.green(`Generated ${subagentCount} subagent configurations in .
|
|
7861
|
+
spinner.succeed(import_chalk2.default.green(`Generated ${subagentCount} subagent configurations in ${toolProfile.agentsDir}/`));
|
|
7496
7862
|
spinner = (0, import_ora2.default)("Generating MCP configuration").start();
|
|
7497
7863
|
const mcpServers = getMCPServersFromSubagents(subagents);
|
|
7498
|
-
await generateMCPConfig(mcpServers);
|
|
7499
|
-
|
|
7864
|
+
await generateMCPConfig(mcpServers, tool);
|
|
7865
|
+
if (toolProfile.mcpFormat === "json") {
|
|
7866
|
+
spinner.succeed(import_chalk2.default.green(`Generated ${toolProfile.mcpConfigPath} (${mcpServers.length} servers)`));
|
|
7867
|
+
} else if (toolProfile.mcpFormat === "toml") {
|
|
7868
|
+
spinner.succeed(import_chalk2.default.green("MCP configuration ready"));
|
|
7869
|
+
await setupCodexMCP(mcpServers);
|
|
7870
|
+
}
|
|
7500
7871
|
spinner = (0, import_ora2.default)("Creating environment template").start();
|
|
7501
7872
|
await generateEnvExample(mcpServers);
|
|
7502
7873
|
spinner.succeed(import_chalk2.default.green("Created .env.example"));
|
|
7503
7874
|
}
|
|
7875
|
+
async function setupCodexMCP(mcpServers) {
|
|
7876
|
+
const existingServers = await getConfiguredCodexMCPServers();
|
|
7877
|
+
const newServers = mcpServers.filter((s) => !existingServers.includes(s));
|
|
7878
|
+
if (newServers.length === 0) {
|
|
7879
|
+
console.log(import_chalk2.default.gray("\n\u2713 All MCP servers already configured"));
|
|
7880
|
+
return;
|
|
7881
|
+
}
|
|
7882
|
+
console.log();
|
|
7883
|
+
for (const serverName of newServers) {
|
|
7884
|
+
const spinner = (0, import_ora2.default)(`Configuring ${serverName}`).start();
|
|
7885
|
+
try {
|
|
7886
|
+
const { args } = buildCodexMCPCommand(serverName);
|
|
7887
|
+
(0, import_child_process4.execSync)(["codex", ...args].join(" "), {
|
|
7888
|
+
stdio: "pipe",
|
|
7889
|
+
env: { ...process.env, CODEX_HOME: path11.join(process.cwd(), ".codex") }
|
|
7890
|
+
});
|
|
7891
|
+
spinner.succeed(import_chalk2.default.green(`Configured ${serverName}`));
|
|
7892
|
+
} catch (error) {
|
|
7893
|
+
spinner.fail(import_chalk2.default.red(`Failed to configure ${serverName}`));
|
|
7894
|
+
console.error(import_chalk2.default.gray(error.message));
|
|
7895
|
+
}
|
|
7896
|
+
}
|
|
7897
|
+
}
|
|
7504
7898
|
|
|
7505
7899
|
// src/cli/index.ts
|
|
7506
7900
|
process.on("uncaughtException", (error) => {
|