@bugzy-ai/bugzy 1.2.0 → 1.3.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 +49 -27
- package/dist/cli/index.cjs +492 -144
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +495 -147
- package/dist/cli/index.js.map +1 -1
- package/dist/index.cjs +85 -30
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +85 -30
- package/dist/index.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.js
CHANGED
|
@@ -560,7 +560,9 @@ Document all findings including:
|
|
|
560
560
|
\`\`\`
|
|
561
561
|
|
|
562
562
|
#### 3.2 Launch Test Runner Agent
|
|
563
|
-
|
|
563
|
+
{{INVOKE_TEST_RUNNER}}
|
|
564
|
+
|
|
565
|
+
Execute the exploration test case with special exploration instructions:
|
|
564
566
|
|
|
565
567
|
\`\`\`
|
|
566
568
|
Execute the exploration test case at ./test-cases/EXPLORATION-TEMP.md with focus on discovery and documentation.
|
|
@@ -1031,10 +1033,10 @@ Before invoking the agent, identify the test cases for the current area:
|
|
|
1031
1033
|
|
|
1032
1034
|
#### Step 2.2: Invoke test-code-generator Agent
|
|
1033
1035
|
|
|
1034
|
-
|
|
1036
|
+
{{INVOKE_TEST_CODE_GENERATOR}} for the current area with the following context:
|
|
1035
1037
|
|
|
1036
1038
|
**Agent Invocation:**
|
|
1037
|
-
"
|
|
1039
|
+
"Automate test cases for the [AREA_NAME] area.
|
|
1038
1040
|
|
|
1039
1041
|
**Context:**
|
|
1040
1042
|
- Area: [AREA_NAME]
|
|
@@ -1174,10 +1176,10 @@ Provide a comprehensive summary showing:
|
|
|
1174
1176
|
role: "documentation-researcher",
|
|
1175
1177
|
contentBlock: `#### 1.4 Gather Product Documentation
|
|
1176
1178
|
|
|
1177
|
-
|
|
1179
|
+
{{INVOKE_DOCUMENTATION_RESEARCHER}} to gather comprehensive product documentation:
|
|
1178
1180
|
|
|
1179
1181
|
\`\`\`
|
|
1180
|
-
|
|
1182
|
+
Explore all available product documentation, specifically focusing on:
|
|
1181
1183
|
- UI elements and workflows
|
|
1182
1184
|
- User interactions and navigation paths
|
|
1183
1185
|
- Form fields and validation rules
|
|
@@ -1191,10 +1193,9 @@ Use the documentation-researcher agent to explore all available product document
|
|
|
1191
1193
|
role: "team-communicator",
|
|
1192
1194
|
contentBlock: `### Step 4.5: Team Communication
|
|
1193
1195
|
|
|
1194
|
-
|
|
1196
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to notify the product team about the new test cases and automated tests:
|
|
1195
1197
|
|
|
1196
1198
|
\`\`\`
|
|
1197
|
-
Use the team-communicator agent to:
|
|
1198
1199
|
1. Post an update about test case and automation creation
|
|
1199
1200
|
2. Provide summary of coverage:
|
|
1200
1201
|
- Number of manual test cases created
|
|
@@ -1463,10 +1464,10 @@ Provide a summary of:
|
|
|
1463
1464
|
role: "documentation-researcher",
|
|
1464
1465
|
contentBlock: `### Step 2: Gather comprehensive project documentation
|
|
1465
1466
|
|
|
1466
|
-
|
|
1467
|
+
{{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.
|
|
1467
1468
|
|
|
1468
1469
|
\`\`\`
|
|
1469
|
-
|
|
1470
|
+
Explore all available project documentation related to: $ARGUMENTS
|
|
1470
1471
|
|
|
1471
1472
|
Specifically gather:
|
|
1472
1473
|
- Product specifications and requirements
|
|
@@ -1491,10 +1492,9 @@ The agent will:
|
|
|
1491
1492
|
role: "team-communicator",
|
|
1492
1493
|
contentBlock: `### Step 7.5: Team Communication
|
|
1493
1494
|
|
|
1494
|
-
|
|
1495
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to notify the product team about the new test plan:
|
|
1495
1496
|
|
|
1496
1497
|
\`\`\`
|
|
1497
|
-
Use the team-communicator agent to:
|
|
1498
1498
|
1. Post an update about the test plan creation
|
|
1499
1499
|
2. Provide a brief summary of coverage areas and key features
|
|
1500
1500
|
3. Mention any areas that need exploration or clarification
|
|
@@ -1747,7 +1747,7 @@ Classify the ambiguity level to determine appropriate response:
|
|
|
1747
1747
|
#### Clarification Approach by Severity
|
|
1748
1748
|
|
|
1749
1749
|
**For CRITICAL/HIGH ambiguity:**
|
|
1750
|
-
1. **
|
|
1750
|
+
1. **{{INVOKE_TEAM_COMMUNICATOR}} to ask specific questions**
|
|
1751
1751
|
2. **WAIT for response before proceeding**
|
|
1752
1752
|
3. **Document the clarification request in event history**
|
|
1753
1753
|
|
|
@@ -2020,7 +2020,7 @@ ${KNOWLEDGE_BASE_UPDATE_INSTRUCTIONS}`,
|
|
|
2020
2020
|
contentBlock: `#### 3.3 Use Documentation Researcher if Needed
|
|
2021
2021
|
For events mentioning unknown features or components:
|
|
2022
2022
|
\`\`\`
|
|
2023
|
-
|
|
2023
|
+
{{INVOKE_DOCUMENTATION_RESEARCHER}} to find information about: [component/feature]
|
|
2024
2024
|
\`\`\``
|
|
2025
2025
|
},
|
|
2026
2026
|
{
|
|
@@ -2029,7 +2029,7 @@ Use documentation-researcher agent to find information about: [component/feature
|
|
|
2029
2029
|
|
|
2030
2030
|
When an issue needs to be tracked (task type: report_bug or update_story):
|
|
2031
2031
|
\`\`\`
|
|
2032
|
-
|
|
2032
|
+
{{INVOKE_ISSUE_TRACKER}}
|
|
2033
2033
|
1. Check for duplicate issues in the tracking system
|
|
2034
2034
|
2. For bugs: Create detailed bug report with:
|
|
2035
2035
|
- Clear, descriptive title
|
|
@@ -2307,7 +2307,7 @@ For each failed test:
|
|
|
2307
2307
|
For each test classified as **[TEST ISSUE]**, use the test-debugger-fixer agent to automatically fix the test:
|
|
2308
2308
|
|
|
2309
2309
|
\`\`\`
|
|
2310
|
-
|
|
2310
|
+
{{INVOKE_TEST_DEBUGGER_FIXER}}
|
|
2311
2311
|
|
|
2312
2312
|
For each failed test classified as a test issue (not a product bug), provide:
|
|
2313
2313
|
- Test run timestamp: [from manifest.timestamp]
|
|
@@ -2402,7 +2402,7 @@ After triage in Step 5.1, for tests classified as **[PRODUCT BUG]**, use the iss
|
|
|
2402
2402
|
For each bug to report, use the issue-tracker agent:
|
|
2403
2403
|
|
|
2404
2404
|
\`\`\`
|
|
2405
|
-
|
|
2405
|
+
{{INVOKE_ISSUE_TRACKER}}
|
|
2406
2406
|
1. Check for duplicate bugs in the tracking system
|
|
2407
2407
|
- The agent will automatically search for similar existing issues
|
|
2408
2408
|
- It maintains memory of recently reported issues
|
|
@@ -2473,10 +2473,11 @@ After issue tracker agent completes, create a summary:
|
|
|
2473
2473
|
role: "team-communicator",
|
|
2474
2474
|
contentBlock: `### Step 6: Team Communication
|
|
2475
2475
|
|
|
2476
|
-
|
|
2476
|
+
{{INVOKE_TEAM_COMMUNICATOR}}
|
|
2477
|
+
|
|
2478
|
+
Notify the product team about test execution:
|
|
2477
2479
|
|
|
2478
2480
|
\`\`\`
|
|
2479
|
-
Use the team-communicator agent to:
|
|
2480
2481
|
1. Post test execution summary with key statistics
|
|
2481
2482
|
2. Highlight critical failures that need immediate attention
|
|
2482
2483
|
3. Share important learnings about product behavior
|
|
@@ -2820,7 +2821,7 @@ Read and analyze the JSON report:
|
|
|
2820
2821
|
For each test classified as **[TEST ISSUE]**, use the test-debugger-fixer agent to automatically fix the test:
|
|
2821
2822
|
|
|
2822
2823
|
\`\`\`
|
|
2823
|
-
|
|
2824
|
+
{{INVOKE_TEST_DEBUGGER_FIXER}}
|
|
2824
2825
|
|
|
2825
2826
|
For each failed test classified as a test issue (not a product bug), provide:
|
|
2826
2827
|
- Test file path: [from JSON report]
|
|
@@ -2861,7 +2862,7 @@ Classification guidelines:
|
|
|
2861
2862
|
#### 4A.4 Fix Test Issues Automatically
|
|
2862
2863
|
|
|
2863
2864
|
For tests classified as [TEST ISSUE]:
|
|
2864
|
-
-
|
|
2865
|
+
- {{INVOKE_TEST_DEBUGGER_FIXER}} to analyze and fix
|
|
2865
2866
|
- Agent debugs with browser if needed
|
|
2866
2867
|
- Applies fix (selector update, wait condition, assertion correction)
|
|
2867
2868
|
- Reruns test to verify fix (10x for flaky tests)
|
|
@@ -2877,7 +2878,7 @@ Track fixed tests with:
|
|
|
2877
2878
|
{{ISSUE_TRACKER_INSTRUCTIONS}}
|
|
2878
2879
|
|
|
2879
2880
|
For tests classified as [PRODUCT BUG]:
|
|
2880
|
-
-
|
|
2881
|
+
- {{INVOKE_ISSUE_TRACKER}} to create bug reports
|
|
2881
2882
|
- Agent checks for duplicates automatically
|
|
2882
2883
|
- Creates detailed report with:
|
|
2883
2884
|
- Title, description, reproduction steps
|
|
@@ -3193,10 +3194,10 @@ Format as comprehensive markdown report for terminal display:
|
|
|
3193
3194
|
|
|
3194
3195
|
{{TEAM_COMMUNICATOR_INSTRUCTIONS}}
|
|
3195
3196
|
|
|
3196
|
-
|
|
3197
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to post concise results to Slack thread:
|
|
3197
3198
|
|
|
3198
3199
|
\`\`\`
|
|
3199
|
-
|
|
3200
|
+
Post verification results.
|
|
3200
3201
|
|
|
3201
3202
|
**Channel**: [from CHANGE_CONTEXT.slackChannel]
|
|
3202
3203
|
**Thread**: [from CHANGE_CONTEXT.slackThread]
|
|
@@ -3377,10 +3378,10 @@ A successful verification includes:
|
|
|
3377
3378
|
role: "documentation-researcher",
|
|
3378
3379
|
contentBlock: `#### Research Project Documentation
|
|
3379
3380
|
|
|
3380
|
-
|
|
3381
|
+
{{INVOKE_DOCUMENTATION_RESEARCHER}} to gather comprehensive context about the changed features:
|
|
3381
3382
|
|
|
3382
3383
|
\`\`\`
|
|
3383
|
-
|
|
3384
|
+
Explore project documentation related to the changes.
|
|
3384
3385
|
|
|
3385
3386
|
Specifically gather:
|
|
3386
3387
|
- Product specifications for affected features
|
|
@@ -3412,10 +3413,9 @@ Use this information to:
|
|
|
3412
3413
|
role: "issue-tracker",
|
|
3413
3414
|
contentBlock: `#### Log Product Bugs
|
|
3414
3415
|
|
|
3415
|
-
For tests classified as **[PRODUCT BUG]**,
|
|
3416
|
+
For tests classified as **[PRODUCT BUG]**, {{INVOKE_ISSUE_TRACKER}} to log bugs:
|
|
3416
3417
|
|
|
3417
3418
|
\`\`\`
|
|
3418
|
-
Use issue-tracker agent to:
|
|
3419
3419
|
1. Check for duplicate bugs in the tracking system
|
|
3420
3420
|
- The agent will automatically search for similar existing issues
|
|
3421
3421
|
- It maintains memory of recently reported issues
|
|
@@ -3464,10 +3464,9 @@ Use issue-tracker agent to:
|
|
|
3464
3464
|
role: "team-communicator",
|
|
3465
3465
|
contentBlock: `#### Team Communication
|
|
3466
3466
|
|
|
3467
|
-
|
|
3467
|
+
{{INVOKE_TEAM_COMMUNICATOR}} to share verification results (primarily for Slack trigger, but can be used for other triggers):
|
|
3468
3468
|
|
|
3469
3469
|
\`\`\`
|
|
3470
|
-
Use the team-communicator agent to:
|
|
3471
3470
|
1. Post verification results summary
|
|
3472
3471
|
2. Highlight critical failures that need immediate attention
|
|
3473
3472
|
3. Share bugs logged with issue tracker links
|
|
@@ -3590,13 +3589,14 @@ var init_tasks = __esm({
|
|
|
3590
3589
|
init_esm_shims();
|
|
3591
3590
|
import { Command } from "commander";
|
|
3592
3591
|
import { readFileSync as readFileSync5 } from "fs";
|
|
3593
|
-
import { join as
|
|
3592
|
+
import { join as join12, dirname as dirname7 } from "path";
|
|
3594
3593
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3595
3594
|
import chalk3 from "chalk";
|
|
3596
3595
|
|
|
3597
3596
|
// src/cli/commands/start.ts
|
|
3598
3597
|
init_esm_shims();
|
|
3599
3598
|
import { spawn } from "child_process";
|
|
3599
|
+
import * as path5 from "path";
|
|
3600
3600
|
import chalk from "chalk";
|
|
3601
3601
|
import ora from "ora";
|
|
3602
3602
|
|
|
@@ -3604,6 +3604,97 @@ import ora from "ora";
|
|
|
3604
3604
|
init_esm_shims();
|
|
3605
3605
|
import * as fs from "fs";
|
|
3606
3606
|
import * as path2 from "path";
|
|
3607
|
+
|
|
3608
|
+
// src/core/tool-profile.ts
|
|
3609
|
+
init_esm_shims();
|
|
3610
|
+
var DEFAULT_TOOL = "claude-code";
|
|
3611
|
+
var CLAUDE_CODE_PROFILE = {
|
|
3612
|
+
id: "claude-code",
|
|
3613
|
+
name: "Claude Code",
|
|
3614
|
+
cliCommand: "claude",
|
|
3615
|
+
commandsDir: ".claude/commands",
|
|
3616
|
+
agentsDir: ".claude/agents",
|
|
3617
|
+
mcpConfigPath: ".mcp.json",
|
|
3618
|
+
mcpFormat: "json",
|
|
3619
|
+
memoryFile: "CLAUDE.md",
|
|
3620
|
+
commandFrontmatter: true,
|
|
3621
|
+
agentFrontmatter: true,
|
|
3622
|
+
commandInvocationPrefix: "/",
|
|
3623
|
+
commandExtension: ".md",
|
|
3624
|
+
agentExtension: ".md"
|
|
3625
|
+
};
|
|
3626
|
+
var CURSOR_PROFILE = {
|
|
3627
|
+
id: "cursor",
|
|
3628
|
+
name: "Cursor",
|
|
3629
|
+
cliCommand: "cursor-agent",
|
|
3630
|
+
commandsDir: ".cursor/commands",
|
|
3631
|
+
agentsDir: ".cursor/agents",
|
|
3632
|
+
mcpConfigPath: ".cursor/mcp.json",
|
|
3633
|
+
mcpFormat: "json",
|
|
3634
|
+
memoryFile: "AGENTS.md",
|
|
3635
|
+
// Cursor now uses AGENTS.md (.cursorrules deprecated as of v0.45+)
|
|
3636
|
+
commandFrontmatter: false,
|
|
3637
|
+
// Cursor uses plain markdown
|
|
3638
|
+
agentFrontmatter: false,
|
|
3639
|
+
// Agent files are plain markdown for CLI invocation
|
|
3640
|
+
commandInvocationPrefix: "/",
|
|
3641
|
+
commandExtension: ".md",
|
|
3642
|
+
agentExtension: ".md"
|
|
3643
|
+
};
|
|
3644
|
+
var CODEX_PROFILE = {
|
|
3645
|
+
id: "codex",
|
|
3646
|
+
name: "Codex CLI",
|
|
3647
|
+
cliCommand: "codex",
|
|
3648
|
+
commandsDir: ".codex/prompts",
|
|
3649
|
+
// Codex uses prompts directory
|
|
3650
|
+
agentsDir: ".codex/agents",
|
|
3651
|
+
mcpConfigPath: ".codex/config.toml",
|
|
3652
|
+
// Project-local via CODEX_HOME
|
|
3653
|
+
mcpFormat: "toml",
|
|
3654
|
+
homeEnvVar: "CODEX_HOME",
|
|
3655
|
+
// Set to project root for project-local config
|
|
3656
|
+
memoryFile: "AGENTS.md",
|
|
3657
|
+
commandFrontmatter: true,
|
|
3658
|
+
// Codex prompts support frontmatter
|
|
3659
|
+
agentFrontmatter: false,
|
|
3660
|
+
// Agent files are plain markdown for CLI invocation
|
|
3661
|
+
commandInvocationPrefix: "/prompts:",
|
|
3662
|
+
commandExtension: ".md",
|
|
3663
|
+
agentExtension: ".md"
|
|
3664
|
+
};
|
|
3665
|
+
var TOOL_PROFILES = {
|
|
3666
|
+
"claude-code": CLAUDE_CODE_PROFILE,
|
|
3667
|
+
"cursor": CURSOR_PROFILE,
|
|
3668
|
+
"codex": CODEX_PROFILE
|
|
3669
|
+
};
|
|
3670
|
+
function getToolProfile(toolId) {
|
|
3671
|
+
const profile = TOOL_PROFILES[toolId];
|
|
3672
|
+
if (!profile) {
|
|
3673
|
+
throw new Error(`Unknown tool: ${toolId}`);
|
|
3674
|
+
}
|
|
3675
|
+
return profile;
|
|
3676
|
+
}
|
|
3677
|
+
function getToolOptions() {
|
|
3678
|
+
return [
|
|
3679
|
+
{
|
|
3680
|
+
value: "claude-code",
|
|
3681
|
+
label: "Claude Code (CLI or Cloud)",
|
|
3682
|
+
hint: "Anthropic's official CLI - recommended"
|
|
3683
|
+
},
|
|
3684
|
+
{
|
|
3685
|
+
value: "cursor",
|
|
3686
|
+
label: "Cursor (Experimental)",
|
|
3687
|
+
hint: "VS Code-based AI editor - experimental support"
|
|
3688
|
+
},
|
|
3689
|
+
{
|
|
3690
|
+
value: "codex",
|
|
3691
|
+
label: "Codex CLI (Experimental)",
|
|
3692
|
+
hint: "OpenAI's terminal-based agent - experimental support"
|
|
3693
|
+
}
|
|
3694
|
+
];
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3697
|
+
// src/cli/utils/config.ts
|
|
3607
3698
|
async function loadConfig(configPath = ".bugzy/config.json") {
|
|
3608
3699
|
const fullPath = path2.join(process.cwd(), configPath);
|
|
3609
3700
|
if (!fs.existsSync(fullPath)) {
|
|
@@ -3612,6 +3703,9 @@ async function loadConfig(configPath = ".bugzy/config.json") {
|
|
|
3612
3703
|
try {
|
|
3613
3704
|
const content = fs.readFileSync(fullPath, "utf-8");
|
|
3614
3705
|
const config = JSON.parse(content);
|
|
3706
|
+
if (!config.tool) {
|
|
3707
|
+
config.tool = DEFAULT_TOOL;
|
|
3708
|
+
}
|
|
3615
3709
|
return config;
|
|
3616
3710
|
} catch (error) {
|
|
3617
3711
|
console.error(`Error loading config from ${fullPath}:`, error);
|
|
@@ -3636,15 +3730,19 @@ function configExists(configPath = ".bugzy/config.json") {
|
|
|
3636
3730
|
const fullPath = path2.join(process.cwd(), configPath);
|
|
3637
3731
|
return fs.existsSync(fullPath);
|
|
3638
3732
|
}
|
|
3639
|
-
function createDefaultConfig(projectName) {
|
|
3733
|
+
function createDefaultConfig(projectName, tool = DEFAULT_TOOL) {
|
|
3640
3734
|
return {
|
|
3641
3735
|
version: "1.0.0",
|
|
3736
|
+
tool,
|
|
3642
3737
|
project: {
|
|
3643
3738
|
name: projectName
|
|
3644
3739
|
},
|
|
3645
3740
|
subagents: {}
|
|
3646
3741
|
};
|
|
3647
3742
|
}
|
|
3743
|
+
function getToolFromConfig(config) {
|
|
3744
|
+
return config.tool || DEFAULT_TOOL;
|
|
3745
|
+
}
|
|
3648
3746
|
|
|
3649
3747
|
// src/cli/utils/env.ts
|
|
3650
3748
|
init_esm_shims();
|
|
@@ -3707,13 +3805,19 @@ function validateEnvVars(mcpServers, envVars) {
|
|
|
3707
3805
|
init_esm_shims();
|
|
3708
3806
|
import * as fs3 from "fs";
|
|
3709
3807
|
import * as path4 from "path";
|
|
3710
|
-
function validateProjectStructure() {
|
|
3808
|
+
async function validateProjectStructure() {
|
|
3809
|
+
const config = await loadConfig();
|
|
3810
|
+
const tool = config ? getToolFromConfig(config) : DEFAULT_TOOL;
|
|
3811
|
+
const toolProfile = getToolProfile(tool);
|
|
3711
3812
|
const requiredDirs = [
|
|
3712
3813
|
".bugzy",
|
|
3713
3814
|
".bugzy/runtime",
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3815
|
+
path4.dirname(toolProfile.commandsDir),
|
|
3816
|
+
// .claude, .cursor, or .codex
|
|
3817
|
+
toolProfile.commandsDir,
|
|
3818
|
+
// .claude/commands, .cursor/commands, .codex/prompts
|
|
3819
|
+
toolProfile.agentsDir
|
|
3820
|
+
// .claude/agents, .cursor/agents, .codex/agents
|
|
3717
3821
|
];
|
|
3718
3822
|
const requiredFiles = [
|
|
3719
3823
|
".bugzy/config.json",
|
|
@@ -3739,10 +3843,10 @@ function validateProjectStructure() {
|
|
|
3739
3843
|
}
|
|
3740
3844
|
return true;
|
|
3741
3845
|
}
|
|
3742
|
-
async function
|
|
3846
|
+
async function checkToolAvailable(command) {
|
|
3743
3847
|
const { spawn: spawn2 } = await import("child_process");
|
|
3744
3848
|
return new Promise((resolve) => {
|
|
3745
|
-
const proc = spawn2("which", [
|
|
3849
|
+
const proc = spawn2("which", [command]);
|
|
3746
3850
|
proc.on("close", (code) => {
|
|
3747
3851
|
resolve(code === 0);
|
|
3748
3852
|
});
|
|
@@ -3787,9 +3891,11 @@ async function startSession(prompt) {
|
|
|
3787
3891
|
process.exit(1);
|
|
3788
3892
|
}
|
|
3789
3893
|
spinner.succeed(chalk.green("Configuration loaded"));
|
|
3894
|
+
const tool = getToolFromConfig(config);
|
|
3895
|
+
const toolProfile = getToolProfile(tool);
|
|
3790
3896
|
spinner = ora("Validating project structure").start();
|
|
3791
3897
|
try {
|
|
3792
|
-
validateProjectStructure();
|
|
3898
|
+
await validateProjectStructure();
|
|
3793
3899
|
spinner.succeed(chalk.green("Project structure validated"));
|
|
3794
3900
|
} catch (error) {
|
|
3795
3901
|
spinner.fail(chalk.red("Invalid project structure"));
|
|
@@ -3797,15 +3903,22 @@ async function startSession(prompt) {
|
|
|
3797
3903
|
console.log(chalk.yellow("\nRun"), chalk.cyan("bugzy setup"), chalk.yellow("to fix the project structure"));
|
|
3798
3904
|
process.exit(1);
|
|
3799
3905
|
}
|
|
3800
|
-
spinner = ora(
|
|
3801
|
-
const
|
|
3802
|
-
if (!
|
|
3803
|
-
spinner.fail(chalk.red(
|
|
3804
|
-
console.log(chalk.yellow(
|
|
3805
|
-
|
|
3906
|
+
spinner = ora(`Checking ${toolProfile.name} availability`).start();
|
|
3907
|
+
const toolAvailable = await checkToolAvailable(toolProfile.cliCommand);
|
|
3908
|
+
if (!toolAvailable) {
|
|
3909
|
+
spinner.fail(chalk.red(`${toolProfile.name} CLI not found`));
|
|
3910
|
+
console.log(chalk.yellow(`
|
|
3911
|
+
Please install ${toolProfile.name}:`));
|
|
3912
|
+
if (tool === "claude-code") {
|
|
3913
|
+
console.log(chalk.cyan(" https://claude.com/claude-code"));
|
|
3914
|
+
} else if (tool === "cursor") {
|
|
3915
|
+
console.log(chalk.cyan(" https://www.cursor.com/"));
|
|
3916
|
+
} else if (tool === "codex") {
|
|
3917
|
+
console.log(chalk.cyan(" npm install -g @openai/codex"));
|
|
3918
|
+
}
|
|
3806
3919
|
process.exit(1);
|
|
3807
3920
|
}
|
|
3808
|
-
spinner.succeed(chalk.green(
|
|
3921
|
+
spinner.succeed(chalk.green(`${toolProfile.name} CLI found`));
|
|
3809
3922
|
spinner = ora("Loading environment variables").start();
|
|
3810
3923
|
const envVars = loadEnvFiles();
|
|
3811
3924
|
const envCount = Object.keys(envVars).length;
|
|
@@ -3823,14 +3936,20 @@ async function startSession(prompt) {
|
|
|
3823
3936
|
process.exit(1);
|
|
3824
3937
|
}
|
|
3825
3938
|
spinner.succeed(chalk.green("All required MCP secrets present"));
|
|
3826
|
-
console.log(chalk.green.bold(
|
|
3939
|
+
console.log(chalk.green.bold(`
|
|
3940
|
+
\u{1F680} Launching ${toolProfile.name}...
|
|
3941
|
+
`));
|
|
3827
3942
|
const args = prompt ? [prompt] : [];
|
|
3828
|
-
const
|
|
3943
|
+
const spawnEnv = { ...process.env, ...envVars };
|
|
3944
|
+
if (toolProfile.homeEnvVar) {
|
|
3945
|
+
spawnEnv[toolProfile.homeEnvVar] = path5.join(process.cwd(), ".codex");
|
|
3946
|
+
}
|
|
3947
|
+
const child = spawn(toolProfile.cliCommand, args, {
|
|
3829
3948
|
cwd: process.cwd(),
|
|
3830
|
-
env:
|
|
3949
|
+
env: spawnEnv,
|
|
3831
3950
|
stdio: "inherit"
|
|
3832
3951
|
});
|
|
3833
|
-
|
|
3952
|
+
child.on("close", (code) => {
|
|
3834
3953
|
if (code === 0) {
|
|
3835
3954
|
console.log(chalk.green("\n\u2713 Session ended successfully"));
|
|
3836
3955
|
} else {
|
|
@@ -3838,15 +3957,16 @@ async function startSession(prompt) {
|
|
|
3838
3957
|
\u2713 Session ended (exit code: ${code})`));
|
|
3839
3958
|
}
|
|
3840
3959
|
});
|
|
3841
|
-
|
|
3842
|
-
console.error(chalk.red(
|
|
3960
|
+
child.on("error", (error) => {
|
|
3961
|
+
console.error(chalk.red(`
|
|
3962
|
+
\u2717 Error launching ${toolProfile.name}:`), error);
|
|
3843
3963
|
process.exit(1);
|
|
3844
3964
|
});
|
|
3845
3965
|
}
|
|
3846
3966
|
|
|
3847
3967
|
// src/cli/commands/setup.ts
|
|
3848
3968
|
init_esm_shims();
|
|
3849
|
-
import * as
|
|
3969
|
+
import * as path12 from "path";
|
|
3850
3970
|
import chalk2 from "chalk";
|
|
3851
3971
|
import inquirer from "inquirer";
|
|
3852
3972
|
import ora2 from "ora";
|
|
@@ -6481,27 +6601,31 @@ function buildSubagentConfig(role, integration) {
|
|
|
6481
6601
|
// src/cli/generators/structure.ts
|
|
6482
6602
|
init_esm_shims();
|
|
6483
6603
|
import * as fs4 from "fs";
|
|
6484
|
-
import * as
|
|
6485
|
-
async function createProjectStructure() {
|
|
6604
|
+
import * as path6 from "path";
|
|
6605
|
+
async function createProjectStructure(tool = DEFAULT_TOOL) {
|
|
6486
6606
|
const cwd = process.cwd();
|
|
6607
|
+
const toolProfile = getToolProfile(tool);
|
|
6487
6608
|
const bugzyDirs = [
|
|
6488
6609
|
".bugzy",
|
|
6489
6610
|
".bugzy/runtime",
|
|
6490
6611
|
".bugzy/runtime/templates"
|
|
6491
6612
|
];
|
|
6492
6613
|
for (const dir of bugzyDirs) {
|
|
6493
|
-
const dirPath =
|
|
6614
|
+
const dirPath = path6.join(cwd, dir);
|
|
6494
6615
|
if (!fs4.existsSync(dirPath)) {
|
|
6495
6616
|
fs4.mkdirSync(dirPath, { recursive: true });
|
|
6496
6617
|
}
|
|
6497
6618
|
}
|
|
6498
|
-
const
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
|
|
6619
|
+
const toolDirs = [
|
|
6620
|
+
path6.dirname(toolProfile.commandsDir),
|
|
6621
|
+
// .claude, .cursor, or .codex
|
|
6622
|
+
toolProfile.commandsDir,
|
|
6623
|
+
// .claude/commands, .cursor/commands, .codex/prompts
|
|
6624
|
+
toolProfile.agentsDir
|
|
6625
|
+
// .claude/agents, .cursor/agents, .codex/agents
|
|
6502
6626
|
];
|
|
6503
|
-
for (const dir of
|
|
6504
|
-
const dirPath =
|
|
6627
|
+
for (const dir of toolDirs) {
|
|
6628
|
+
const dirPath = path6.join(cwd, dir);
|
|
6505
6629
|
if (!fs4.existsSync(dirPath)) {
|
|
6506
6630
|
fs4.mkdirSync(dirPath, { recursive: true });
|
|
6507
6631
|
}
|
|
@@ -6509,69 +6633,69 @@ async function createProjectStructure() {
|
|
|
6509
6633
|
await createRuntimeFiles();
|
|
6510
6634
|
}
|
|
6511
6635
|
function getTemplatesDir() {
|
|
6512
|
-
return
|
|
6636
|
+
return path6.join(__dirname, "../../templates/init");
|
|
6513
6637
|
}
|
|
6514
6638
|
async function createRuntimeFiles() {
|
|
6515
6639
|
const cwd = process.cwd();
|
|
6516
6640
|
const templatesDir = getTemplatesDir();
|
|
6517
|
-
const projectContextPath =
|
|
6641
|
+
const projectContextPath = path6.join(cwd, ".bugzy/runtime/project-context.md");
|
|
6518
6642
|
if (!fs4.existsSync(projectContextPath)) {
|
|
6519
|
-
const templatePath =
|
|
6643
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/project-context.md");
|
|
6520
6644
|
let content = fs4.readFileSync(templatePath, "utf-8");
|
|
6521
|
-
const projectName =
|
|
6645
|
+
const projectName = path6.basename(cwd);
|
|
6522
6646
|
content = content.replace(/\{\{PROJECT_NAME\}\}/g, projectName);
|
|
6523
6647
|
content = content.replace(/\{\{CUSTOMER_NAME\}\}/g, "[To be filled]");
|
|
6524
6648
|
content = content.replace(/\{\{BUG_TRACKING_SYSTEM\}\}/g, "[To be filled]");
|
|
6525
6649
|
content = content.replace(/\{\{DOCUMENTATION_SYSTEM\}\}/g, "[To be filled]");
|
|
6526
6650
|
fs4.writeFileSync(projectContextPath, content, "utf-8");
|
|
6527
6651
|
}
|
|
6528
|
-
const testPlanTemplatePath =
|
|
6652
|
+
const testPlanTemplatePath = path6.join(cwd, ".bugzy/runtime/templates/test-plan-template.md");
|
|
6529
6653
|
if (!fs4.existsSync(testPlanTemplatePath)) {
|
|
6530
|
-
const templatePath =
|
|
6654
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/templates/test-plan-template.md");
|
|
6531
6655
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6532
6656
|
fs4.writeFileSync(testPlanTemplatePath, content, "utf-8");
|
|
6533
6657
|
}
|
|
6534
|
-
const bestPracticesPath =
|
|
6658
|
+
const bestPracticesPath = path6.join(cwd, ".bugzy/runtime/testing-best-practices.md");
|
|
6535
6659
|
if (!fs4.existsSync(bestPracticesPath)) {
|
|
6536
|
-
const templatePath =
|
|
6660
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/testing-best-practices.md");
|
|
6537
6661
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6538
6662
|
fs4.writeFileSync(bestPracticesPath, content, "utf-8");
|
|
6539
6663
|
}
|
|
6540
|
-
const testResultSchemaPath =
|
|
6664
|
+
const testResultSchemaPath = path6.join(cwd, ".bugzy/runtime/templates/test-result-schema.md");
|
|
6541
6665
|
if (!fs4.existsSync(testResultSchemaPath)) {
|
|
6542
|
-
const templatePath =
|
|
6666
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/templates/test-result-schema.md");
|
|
6543
6667
|
if (fs4.existsSync(templatePath)) {
|
|
6544
6668
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6545
6669
|
fs4.writeFileSync(testResultSchemaPath, content, "utf-8");
|
|
6546
6670
|
}
|
|
6547
6671
|
}
|
|
6548
|
-
const knowledgeBasePath =
|
|
6672
|
+
const knowledgeBasePath = path6.join(cwd, ".bugzy/runtime/knowledge-base.md");
|
|
6549
6673
|
if (!fs4.existsSync(knowledgeBasePath)) {
|
|
6550
|
-
const templatePath =
|
|
6674
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/knowledge-base.md");
|
|
6551
6675
|
if (fs4.existsSync(templatePath)) {
|
|
6552
6676
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6553
6677
|
fs4.writeFileSync(knowledgeBasePath, content, "utf-8");
|
|
6554
6678
|
}
|
|
6555
6679
|
}
|
|
6556
|
-
const knowledgeMaintenancePath =
|
|
6680
|
+
const knowledgeMaintenancePath = path6.join(cwd, ".bugzy/runtime/knowledge-maintenance-guide.md");
|
|
6557
6681
|
if (!fs4.existsSync(knowledgeMaintenancePath)) {
|
|
6558
|
-
const templatePath =
|
|
6682
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/knowledge-maintenance-guide.md");
|
|
6559
6683
|
if (fs4.existsSync(templatePath)) {
|
|
6560
6684
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6561
6685
|
fs4.writeFileSync(knowledgeMaintenancePath, content, "utf-8");
|
|
6562
6686
|
}
|
|
6563
6687
|
}
|
|
6564
|
-
const subagentMemoryPath =
|
|
6688
|
+
const subagentMemoryPath = path6.join(cwd, ".bugzy/runtime/subagent-memory-guide.md");
|
|
6565
6689
|
if (!fs4.existsSync(subagentMemoryPath)) {
|
|
6566
|
-
const templatePath =
|
|
6690
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/subagent-memory-guide.md");
|
|
6567
6691
|
if (fs4.existsSync(templatePath)) {
|
|
6568
6692
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6569
6693
|
fs4.writeFileSync(subagentMemoryPath, content, "utf-8");
|
|
6570
6694
|
}
|
|
6571
6695
|
}
|
|
6572
|
-
const testExecutionStrategyPath =
|
|
6696
|
+
const testExecutionStrategyPath = path6.join(cwd, ".bugzy/runtime/test-execution-strategy.md");
|
|
6573
6697
|
if (!fs4.existsSync(testExecutionStrategyPath)) {
|
|
6574
|
-
const templatePath =
|
|
6698
|
+
const templatePath = path6.join(templatesDir, ".bugzy/runtime/test-execution-strategy.md");
|
|
6575
6699
|
if (fs4.existsSync(templatePath)) {
|
|
6576
6700
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6577
6701
|
fs4.writeFileSync(testExecutionStrategyPath, content, "utf-8");
|
|
@@ -6581,18 +6705,28 @@ async function createRuntimeFiles() {
|
|
|
6581
6705
|
async function generateClaudeMd() {
|
|
6582
6706
|
const cwd = process.cwd();
|
|
6583
6707
|
const templatesDir = getTemplatesDir();
|
|
6584
|
-
const claudeMdPath =
|
|
6708
|
+
const claudeMdPath = path6.join(cwd, "CLAUDE.md");
|
|
6585
6709
|
if (!fs4.existsSync(claudeMdPath)) {
|
|
6586
|
-
const templatePath =
|
|
6710
|
+
const templatePath = path6.join(templatesDir, "CLAUDE.md");
|
|
6587
6711
|
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6588
6712
|
fs4.writeFileSync(claudeMdPath, content, "utf-8");
|
|
6589
6713
|
}
|
|
6590
6714
|
}
|
|
6715
|
+
async function generateAgentsMd() {
|
|
6716
|
+
const cwd = process.cwd();
|
|
6717
|
+
const templatesDir = getTemplatesDir();
|
|
6718
|
+
const agentsMdPath = path6.join(cwd, "AGENTS.md");
|
|
6719
|
+
if (!fs4.existsSync(agentsMdPath)) {
|
|
6720
|
+
const templatePath = path6.join(templatesDir, "AGENTS.md");
|
|
6721
|
+
const content = fs4.readFileSync(templatePath, "utf-8");
|
|
6722
|
+
fs4.writeFileSync(agentsMdPath, content, "utf-8");
|
|
6723
|
+
}
|
|
6724
|
+
}
|
|
6591
6725
|
async function updateGitignore() {
|
|
6592
6726
|
const cwd = process.cwd();
|
|
6593
|
-
const gitignorePath =
|
|
6727
|
+
const gitignorePath = path6.join(cwd, ".gitignore");
|
|
6594
6728
|
const templatesDir = getTemplatesDir();
|
|
6595
|
-
const templatePath =
|
|
6729
|
+
const templatePath = path6.join(templatesDir, ".gitignore-template");
|
|
6596
6730
|
const bugzyEntries = fs4.readFileSync(templatePath, "utf-8");
|
|
6597
6731
|
if (fs4.existsSync(gitignorePath)) {
|
|
6598
6732
|
const content = fs4.readFileSync(gitignorePath, "utf-8");
|
|
@@ -6608,7 +6742,7 @@ async function updateGitignore() {
|
|
|
6608
6742
|
init_esm_shims();
|
|
6609
6743
|
init_tasks();
|
|
6610
6744
|
import * as fs5 from "fs";
|
|
6611
|
-
import * as
|
|
6745
|
+
import * as path7 from "path";
|
|
6612
6746
|
|
|
6613
6747
|
// src/core/task-builder.ts
|
|
6614
6748
|
init_esm_shims();
|
|
@@ -6657,22 +6791,80 @@ function buildTaskDefinition(taskSlug, projectSubAgents) {
|
|
|
6657
6791
|
};
|
|
6658
6792
|
}
|
|
6659
6793
|
|
|
6794
|
+
// src/core/tool-strings.ts
|
|
6795
|
+
init_esm_shims();
|
|
6796
|
+
var TOOL_STRINGS = {
|
|
6797
|
+
"claude-code": {
|
|
6798
|
+
INVOKE_TEST_RUNNER: "Use the test-runner subagent to execute the tests",
|
|
6799
|
+
INVOKE_TEST_DEBUGGER_FIXER: "Use the test-debugger-fixer subagent to debug and fix the failing test",
|
|
6800
|
+
INVOKE_TEST_CODE_GENERATOR: "Use the test-code-generator subagent to generate automated test code",
|
|
6801
|
+
INVOKE_TEAM_COMMUNICATOR: "Use the team-communicator subagent to notify the team",
|
|
6802
|
+
INVOKE_ISSUE_TRACKER: "Use the issue-tracker subagent to create or update issues",
|
|
6803
|
+
INVOKE_DOCUMENTATION_RESEARCHER: "Use the documentation-researcher subagent to search and gather documentation"
|
|
6804
|
+
},
|
|
6805
|
+
"cursor": {
|
|
6806
|
+
INVOKE_TEST_RUNNER: 'Run the test-runner agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/test-runner.md)" --output-format text\n```',
|
|
6807
|
+
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```',
|
|
6808
|
+
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```',
|
|
6809
|
+
INVOKE_TEAM_COMMUNICATOR: 'Run the team-communicator agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/team-communicator.md)" --output-format text\n```',
|
|
6810
|
+
INVOKE_ISSUE_TRACKER: 'Run the issue-tracker agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/issue-tracker.md)" --output-format text\n```',
|
|
6811
|
+
INVOKE_DOCUMENTATION_RESEARCHER: 'Run the documentation-researcher agent:\n```bash\ncursor-agent -p "$(cat .cursor/agents/documentation-researcher.md)" --output-format text\n```'
|
|
6812
|
+
},
|
|
6813
|
+
"codex": {
|
|
6814
|
+
INVOKE_TEST_RUNNER: 'Run the test-runner agent:\n```bash\ncodex -p "$(cat .codex/agents/test-runner.md)"\n```',
|
|
6815
|
+
INVOKE_TEST_DEBUGGER_FIXER: 'Run the test-debugger-fixer agent:\n```bash\ncodex -p "$(cat .codex/agents/test-debugger-fixer.md)"\n```',
|
|
6816
|
+
INVOKE_TEST_CODE_GENERATOR: 'Run the test-code-generator agent:\n```bash\ncodex -p "$(cat .codex/agents/test-code-generator.md)"\n```',
|
|
6817
|
+
INVOKE_TEAM_COMMUNICATOR: 'Run the team-communicator agent:\n```bash\ncodex -p "$(cat .codex/agents/team-communicator.md)"\n```',
|
|
6818
|
+
INVOKE_ISSUE_TRACKER: 'Run the issue-tracker agent:\n```bash\ncodex -p "$(cat .codex/agents/issue-tracker.md)"\n```',
|
|
6819
|
+
INVOKE_DOCUMENTATION_RESEARCHER: 'Run the documentation-researcher agent:\n```bash\ncodex -p "$(cat .codex/agents/documentation-researcher.md)"\n```'
|
|
6820
|
+
}
|
|
6821
|
+
};
|
|
6822
|
+
function getToolString(toolId, key) {
|
|
6823
|
+
const toolStrings = TOOL_STRINGS[toolId];
|
|
6824
|
+
if (!toolStrings) {
|
|
6825
|
+
throw new Error(`Unknown tool: ${toolId}`);
|
|
6826
|
+
}
|
|
6827
|
+
const value = toolStrings[key];
|
|
6828
|
+
if (!value) {
|
|
6829
|
+
throw new Error(`Unknown string key: ${key} for tool: ${toolId}`);
|
|
6830
|
+
}
|
|
6831
|
+
return value;
|
|
6832
|
+
}
|
|
6833
|
+
function replaceInvocationPlaceholders(content, toolId) {
|
|
6834
|
+
let result = content;
|
|
6835
|
+
const keys = [
|
|
6836
|
+
"INVOKE_TEST_RUNNER",
|
|
6837
|
+
"INVOKE_TEST_DEBUGGER_FIXER",
|
|
6838
|
+
"INVOKE_TEST_CODE_GENERATOR",
|
|
6839
|
+
"INVOKE_TEAM_COMMUNICATOR",
|
|
6840
|
+
"INVOKE_ISSUE_TRACKER",
|
|
6841
|
+
"INVOKE_DOCUMENTATION_RESEARCHER"
|
|
6842
|
+
];
|
|
6843
|
+
for (const key of keys) {
|
|
6844
|
+
const placeholder = `{{${key}}}`;
|
|
6845
|
+
const replacement = getToolString(toolId, key);
|
|
6846
|
+
result = result.replace(new RegExp(placeholder, "g"), replacement);
|
|
6847
|
+
}
|
|
6848
|
+
return result;
|
|
6849
|
+
}
|
|
6850
|
+
|
|
6660
6851
|
// src/cli/generators/commands.ts
|
|
6661
6852
|
var COMMAND_FILTER = {
|
|
6662
6853
|
// Cloud-only commands (skip in local environment)
|
|
6663
6854
|
"handle-message": false,
|
|
6664
6855
|
"process-event": false
|
|
6665
6856
|
};
|
|
6666
|
-
async function generateCommands(subagents) {
|
|
6857
|
+
async function generateCommands(subagents, tool = DEFAULT_TOOL) {
|
|
6667
6858
|
const cwd = process.cwd();
|
|
6668
|
-
const
|
|
6859
|
+
const toolProfile = getToolProfile(tool);
|
|
6860
|
+
const commandsDir = path7.join(cwd, toolProfile.commandsDir);
|
|
6669
6861
|
if (!fs5.existsSync(commandsDir)) {
|
|
6670
6862
|
fs5.mkdirSync(commandsDir, { recursive: true });
|
|
6671
6863
|
}
|
|
6672
6864
|
const existingFiles = fs5.readdirSync(commandsDir);
|
|
6673
6865
|
for (const file of existingFiles) {
|
|
6674
6866
|
if (file.endsWith(".md")) {
|
|
6675
|
-
fs5.unlinkSync(
|
|
6867
|
+
fs5.unlinkSync(path7.join(commandsDir, file));
|
|
6676
6868
|
}
|
|
6677
6869
|
}
|
|
6678
6870
|
const projectSubAgents = Object.entries(subagents).map(
|
|
@@ -6686,18 +6878,35 @@ async function generateCommands(subagents) {
|
|
|
6686
6878
|
const outputSlug = typeof filterValue === "string" ? filterValue : slug;
|
|
6687
6879
|
try {
|
|
6688
6880
|
const taskDef = buildTaskDefinition(slug, projectSubAgents);
|
|
6689
|
-
const
|
|
6690
|
-
const
|
|
6881
|
+
const processedContent = replaceInvocationPlaceholders(taskDef.content, tool);
|
|
6882
|
+
const content = formatCommandMarkdown(taskDef.frontmatter, processedContent, toolProfile.commandFrontmatter);
|
|
6883
|
+
const fileName = `${outputSlug}${toolProfile.commandExtension}`;
|
|
6884
|
+
const filePath = path7.join(commandsDir, fileName);
|
|
6691
6885
|
fs5.writeFileSync(filePath, content, "utf-8");
|
|
6692
6886
|
} catch (error) {
|
|
6693
|
-
const
|
|
6694
|
-
const
|
|
6887
|
+
const processedContent = replaceInvocationPlaceholders(template.baseContent, tool);
|
|
6888
|
+
const content = formatCommandMarkdown(template.frontmatter, processedContent, toolProfile.commandFrontmatter);
|
|
6889
|
+
const fileName = `${outputSlug}${toolProfile.commandExtension}`;
|
|
6890
|
+
const filePath = path7.join(commandsDir, fileName);
|
|
6695
6891
|
fs5.writeFileSync(filePath, content, "utf-8");
|
|
6696
6892
|
console.warn(`Warning: Generated ${outputSlug} without required subagents: ${error.message}`);
|
|
6697
6893
|
}
|
|
6698
6894
|
}
|
|
6699
6895
|
}
|
|
6700
|
-
function formatCommandMarkdown(frontmatter, content) {
|
|
6896
|
+
function formatCommandMarkdown(frontmatter, content, includeFrontmatter) {
|
|
6897
|
+
if (!includeFrontmatter) {
|
|
6898
|
+
const lines2 = [];
|
|
6899
|
+
if (frontmatter.description) {
|
|
6900
|
+
lines2.push(`# ${frontmatter.description}`);
|
|
6901
|
+
lines2.push("");
|
|
6902
|
+
}
|
|
6903
|
+
if (frontmatter["argument-hint"]) {
|
|
6904
|
+
lines2.push(`**Arguments**: ${frontmatter["argument-hint"]}`);
|
|
6905
|
+
lines2.push("");
|
|
6906
|
+
}
|
|
6907
|
+
lines2.push(content);
|
|
6908
|
+
return lines2.join("\n");
|
|
6909
|
+
}
|
|
6701
6910
|
const lines = ["---"];
|
|
6702
6911
|
for (const [key, value] of Object.entries(frontmatter)) {
|
|
6703
6912
|
if (value !== void 0 && value !== null) {
|
|
@@ -6714,17 +6923,18 @@ function formatCommandMarkdown(frontmatter, content) {
|
|
|
6714
6923
|
// src/cli/generators/agents.ts
|
|
6715
6924
|
init_esm_shims();
|
|
6716
6925
|
import * as fs6 from "fs";
|
|
6717
|
-
import * as
|
|
6718
|
-
async function generateAgents(subagents) {
|
|
6926
|
+
import * as path8 from "path";
|
|
6927
|
+
async function generateAgents(subagents, tool = DEFAULT_TOOL) {
|
|
6719
6928
|
const cwd = process.cwd();
|
|
6720
|
-
const
|
|
6929
|
+
const toolProfile = getToolProfile(tool);
|
|
6930
|
+
const agentsDir = path8.join(cwd, toolProfile.agentsDir);
|
|
6721
6931
|
if (!fs6.existsSync(agentsDir)) {
|
|
6722
6932
|
fs6.mkdirSync(agentsDir, { recursive: true });
|
|
6723
6933
|
}
|
|
6724
6934
|
const existingFiles = fs6.readdirSync(agentsDir);
|
|
6725
6935
|
for (const file of existingFiles) {
|
|
6726
6936
|
if (file.endsWith(".md")) {
|
|
6727
|
-
fs6.unlinkSync(
|
|
6937
|
+
fs6.unlinkSync(path8.join(agentsDir, file));
|
|
6728
6938
|
}
|
|
6729
6939
|
}
|
|
6730
6940
|
for (const [role, integration] of Object.entries(subagents)) {
|
|
@@ -6733,12 +6943,16 @@ async function generateAgents(subagents) {
|
|
|
6733
6943
|
console.warn(`Warning: Could not load template for ${role} with ${integration}`);
|
|
6734
6944
|
continue;
|
|
6735
6945
|
}
|
|
6736
|
-
const content = formatAgentMarkdown(config.frontmatter, config.content);
|
|
6737
|
-
const
|
|
6946
|
+
const content = formatAgentMarkdown(config.frontmatter, config.content, toolProfile.agentFrontmatter);
|
|
6947
|
+
const fileName = `${role}${toolProfile.agentExtension}`;
|
|
6948
|
+
const filePath = path8.join(agentsDir, fileName);
|
|
6738
6949
|
fs6.writeFileSync(filePath, content, "utf-8");
|
|
6739
6950
|
}
|
|
6740
6951
|
}
|
|
6741
|
-
function formatAgentMarkdown(frontmatter, content) {
|
|
6952
|
+
function formatAgentMarkdown(frontmatter, content, includeFrontmatter) {
|
|
6953
|
+
if (!includeFrontmatter) {
|
|
6954
|
+
return content;
|
|
6955
|
+
}
|
|
6742
6956
|
const lines = ["---"];
|
|
6743
6957
|
for (const [key, value] of Object.entries(frontmatter)) {
|
|
6744
6958
|
if (value !== void 0 && value !== null) {
|
|
@@ -6759,7 +6973,8 @@ function formatAgentMarkdown(frontmatter, content) {
|
|
|
6759
6973
|
// src/cli/generators/mcp.ts
|
|
6760
6974
|
init_esm_shims();
|
|
6761
6975
|
import * as fs7 from "fs";
|
|
6762
|
-
import * as
|
|
6976
|
+
import * as path9 from "path";
|
|
6977
|
+
import { execSync } from "child_process";
|
|
6763
6978
|
|
|
6764
6979
|
// src/mcp/index.ts
|
|
6765
6980
|
init_esm_shims();
|
|
@@ -6928,12 +7143,59 @@ function buildMCPConfig(requiredServers, target = "container") {
|
|
|
6928
7143
|
}
|
|
6929
7144
|
|
|
6930
7145
|
// src/cli/generators/mcp.ts
|
|
6931
|
-
async function generateMCPConfig(mcpServers) {
|
|
7146
|
+
async function generateMCPConfig(mcpServers, tool = DEFAULT_TOOL) {
|
|
6932
7147
|
const cwd = process.cwd();
|
|
6933
|
-
const
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
7148
|
+
const toolProfile = getToolProfile(tool);
|
|
7149
|
+
if (toolProfile.mcpFormat === "json") {
|
|
7150
|
+
const mcpConfigPath = path9.join(cwd, toolProfile.mcpConfigPath);
|
|
7151
|
+
const mcpDir = path9.dirname(mcpConfigPath);
|
|
7152
|
+
if (!fs7.existsSync(mcpDir)) {
|
|
7153
|
+
fs7.mkdirSync(mcpDir, { recursive: true });
|
|
7154
|
+
}
|
|
7155
|
+
const mcpConfig = buildMCPConfig(mcpServers, "local");
|
|
7156
|
+
const content = JSON.stringify(mcpConfig, null, 2);
|
|
7157
|
+
fs7.writeFileSync(mcpConfigPath, content, "utf-8");
|
|
7158
|
+
} else if (toolProfile.mcpFormat === "toml") {
|
|
7159
|
+
return;
|
|
7160
|
+
}
|
|
7161
|
+
}
|
|
7162
|
+
function buildCodexMCPCommand(serverName) {
|
|
7163
|
+
const serverTemplate = MCP_SERVERS[serverName];
|
|
7164
|
+
if (!serverTemplate) {
|
|
7165
|
+
throw new Error(`Unknown MCP server: ${serverName}`);
|
|
7166
|
+
}
|
|
7167
|
+
const args = ["mcp", "add", `bugzy-${serverName}`];
|
|
7168
|
+
const envVars = [];
|
|
7169
|
+
if (serverTemplate.config.env) {
|
|
7170
|
+
for (const [key, value] of Object.entries(serverTemplate.config.env)) {
|
|
7171
|
+
const match = value.match(/\$\{([A-Z_]+)\}/);
|
|
7172
|
+
if (match) {
|
|
7173
|
+
args.push("--env", `${key}=$${match[1]}`);
|
|
7174
|
+
envVars.push(match[1]);
|
|
7175
|
+
}
|
|
7176
|
+
}
|
|
7177
|
+
}
|
|
7178
|
+
args.push("--", serverTemplate.config.command);
|
|
7179
|
+
if (serverTemplate.config.args?.length) {
|
|
7180
|
+
args.push(...serverTemplate.config.args);
|
|
7181
|
+
}
|
|
7182
|
+
return { args, envVars };
|
|
7183
|
+
}
|
|
7184
|
+
async function getConfiguredCodexMCPServers() {
|
|
7185
|
+
try {
|
|
7186
|
+
const output = execSync("codex mcp list", {
|
|
7187
|
+
encoding: "utf-8",
|
|
7188
|
+
env: { ...process.env, CODEX_HOME: path9.join(process.cwd(), ".codex") },
|
|
7189
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
7190
|
+
});
|
|
7191
|
+
const lines = output.split("\n");
|
|
7192
|
+
return lines.filter((line) => line.includes("bugzy-")).map((line) => {
|
|
7193
|
+
const match = line.match(/bugzy-([a-z-]+)/);
|
|
7194
|
+
return match ? match[1] : null;
|
|
7195
|
+
}).filter((name) => name !== null);
|
|
7196
|
+
} catch {
|
|
7197
|
+
return [];
|
|
7198
|
+
}
|
|
6937
7199
|
}
|
|
6938
7200
|
function getMCPServersFromSubagents(subagents) {
|
|
6939
7201
|
const mcps = /* @__PURE__ */ new Set();
|
|
@@ -6943,13 +7205,16 @@ function getMCPServersFromSubagents(subagents) {
|
|
|
6943
7205
|
return Array.from(mcps);
|
|
6944
7206
|
}
|
|
6945
7207
|
|
|
7208
|
+
// src/cli/commands/setup.ts
|
|
7209
|
+
import { execSync as execSync3 } from "child_process";
|
|
7210
|
+
|
|
6946
7211
|
// src/cli/generators/env.ts
|
|
6947
7212
|
init_esm_shims();
|
|
6948
7213
|
import * as fs8 from "fs";
|
|
6949
|
-
import * as
|
|
7214
|
+
import * as path10 from "path";
|
|
6950
7215
|
async function generateEnvExample(mcpServers) {
|
|
6951
7216
|
const cwd = process.cwd();
|
|
6952
|
-
const envExamplePath =
|
|
7217
|
+
const envExamplePath = path10.join(cwd, ".env.example");
|
|
6953
7218
|
const header = `# ============================================
|
|
6954
7219
|
# Bugzy OSS - Environment Variables
|
|
6955
7220
|
# ============================================
|
|
@@ -7009,8 +7274,8 @@ GITHUB_TOKEN=`
|
|
|
7009
7274
|
// src/cli/generators/scaffold-playwright.ts
|
|
7010
7275
|
init_esm_shims();
|
|
7011
7276
|
import * as fs9 from "fs";
|
|
7012
|
-
import * as
|
|
7013
|
-
import { execSync } from "child_process";
|
|
7277
|
+
import * as path11 from "path";
|
|
7278
|
+
import { execSync as execSync2 } from "child_process";
|
|
7014
7279
|
async function scaffoldPlaywrightProject(options) {
|
|
7015
7280
|
const { projectName, targetDir, skipInstall = false } = options;
|
|
7016
7281
|
console.log("\n\u{1F3AD} Scaffolding Playwright test automation project...\n");
|
|
@@ -7043,7 +7308,7 @@ async function createDirectoryStructure(targetDir) {
|
|
|
7043
7308
|
"test-runs"
|
|
7044
7309
|
];
|
|
7045
7310
|
for (const dir of directories) {
|
|
7046
|
-
const fullPath =
|
|
7311
|
+
const fullPath = path11.join(targetDir, dir);
|
|
7047
7312
|
if (!fs9.existsSync(fullPath)) {
|
|
7048
7313
|
fs9.mkdirSync(fullPath, { recursive: true });
|
|
7049
7314
|
console.log(` \u2713 Created ${dir}/`);
|
|
@@ -7052,11 +7317,11 @@ async function createDirectoryStructure(targetDir) {
|
|
|
7052
7317
|
}
|
|
7053
7318
|
async function copyTemplateFiles(targetDir, projectName) {
|
|
7054
7319
|
const possiblePaths = [
|
|
7055
|
-
|
|
7320
|
+
path11.join(__dirname, "../../templates/playwright"),
|
|
7056
7321
|
// When running from dist
|
|
7057
|
-
|
|
7322
|
+
path11.join(process.cwd(), "templates/playwright"),
|
|
7058
7323
|
// When running from project root
|
|
7059
|
-
|
|
7324
|
+
path11.join(__dirname, "../../../templates/playwright")
|
|
7060
7325
|
// When running tests
|
|
7061
7326
|
];
|
|
7062
7327
|
let templatesDir = "";
|
|
@@ -7069,9 +7334,9 @@ async function copyTemplateFiles(targetDir, projectName) {
|
|
|
7069
7334
|
if (!templatesDir) {
|
|
7070
7335
|
throw new Error("Templates directory not found. Searched paths: " + possiblePaths.join(", "));
|
|
7071
7336
|
}
|
|
7072
|
-
const initTemplatesDir =
|
|
7073
|
-
const testRunsReadmeSrc =
|
|
7074
|
-
const testRunsReadmeDest =
|
|
7337
|
+
const initTemplatesDir = path11.join(__dirname, "../../templates/init");
|
|
7338
|
+
const testRunsReadmeSrc = path11.join(initTemplatesDir, "test-runs/README.md");
|
|
7339
|
+
const testRunsReadmeDest = path11.join(targetDir, "test-runs/README.md");
|
|
7075
7340
|
if (fs9.existsSync(testRunsReadmeSrc)) {
|
|
7076
7341
|
const content = fs9.readFileSync(testRunsReadmeSrc, "utf-8");
|
|
7077
7342
|
fs9.writeFileSync(testRunsReadmeDest, content, "utf-8");
|
|
@@ -7115,8 +7380,8 @@ async function copyTemplateFiles(targetDir, projectName) {
|
|
|
7115
7380
|
}
|
|
7116
7381
|
];
|
|
7117
7382
|
for (const template of templates) {
|
|
7118
|
-
const srcPath =
|
|
7119
|
-
const destPath =
|
|
7383
|
+
const srcPath = path11.join(templatesDir, template.src);
|
|
7384
|
+
const destPath = path11.join(targetDir, template.dest);
|
|
7120
7385
|
if (fs9.existsSync(srcPath)) {
|
|
7121
7386
|
let content = fs9.readFileSync(srcPath, "utf-8");
|
|
7122
7387
|
if (template.process) {
|
|
@@ -7126,7 +7391,7 @@ async function copyTemplateFiles(targetDir, projectName) {
|
|
|
7126
7391
|
DATE: (/* @__PURE__ */ new Date()).toISOString().split("T")[0]
|
|
7127
7392
|
});
|
|
7128
7393
|
}
|
|
7129
|
-
const destDir =
|
|
7394
|
+
const destDir = path11.dirname(destPath);
|
|
7130
7395
|
if (!fs9.existsSync(destDir)) {
|
|
7131
7396
|
fs9.mkdirSync(destDir, { recursive: true });
|
|
7132
7397
|
}
|
|
@@ -7146,7 +7411,7 @@ function processTemplate(content, values) {
|
|
|
7146
7411
|
return processed;
|
|
7147
7412
|
}
|
|
7148
7413
|
async function updateGitignore2(targetDir) {
|
|
7149
|
-
const gitignorePath =
|
|
7414
|
+
const gitignorePath = path11.join(targetDir, ".gitignore");
|
|
7150
7415
|
const playwrightEntries = `
|
|
7151
7416
|
# Playwright
|
|
7152
7417
|
test-results/
|
|
@@ -7166,7 +7431,7 @@ tests/.auth/
|
|
|
7166
7431
|
}
|
|
7167
7432
|
}
|
|
7168
7433
|
async function createPackageJson(targetDir, projectName) {
|
|
7169
|
-
const packageJsonPath =
|
|
7434
|
+
const packageJsonPath = path11.join(targetDir, "package.json");
|
|
7170
7435
|
const recommendedDeps = {
|
|
7171
7436
|
"@playwright/test": "^1.48.0",
|
|
7172
7437
|
"@types/node": "^20.0.0",
|
|
@@ -7222,7 +7487,7 @@ async function installDependencies(targetDir) {
|
|
|
7222
7487
|
console.log(`
|
|
7223
7488
|
\u{1F4E6} Installing dependencies using ${packageManager}...`);
|
|
7224
7489
|
const installCommand = packageManager === "pnpm" ? "pnpm install" : packageManager === "yarn" ? "yarn install" : "npm install";
|
|
7225
|
-
|
|
7490
|
+
execSync2(installCommand, {
|
|
7226
7491
|
cwd: targetDir,
|
|
7227
7492
|
stdio: "inherit"
|
|
7228
7493
|
});
|
|
@@ -7233,17 +7498,17 @@ async function installDependencies(targetDir) {
|
|
|
7233
7498
|
}
|
|
7234
7499
|
}
|
|
7235
7500
|
function detectPackageManager(targetDir) {
|
|
7236
|
-
if (fs9.existsSync(
|
|
7501
|
+
if (fs9.existsSync(path11.join(targetDir, "pnpm-lock.yaml"))) {
|
|
7237
7502
|
return "pnpm";
|
|
7238
7503
|
}
|
|
7239
|
-
if (fs9.existsSync(
|
|
7504
|
+
if (fs9.existsSync(path11.join(targetDir, "yarn.lock"))) {
|
|
7240
7505
|
return "yarn";
|
|
7241
7506
|
}
|
|
7242
7507
|
return "npm";
|
|
7243
7508
|
}
|
|
7244
7509
|
function isPlaywrightScaffolded(targetDir) {
|
|
7245
|
-
const playwrightConfig =
|
|
7246
|
-
const testsDir =
|
|
7510
|
+
const playwrightConfig = path11.join(targetDir, "playwright.config.ts");
|
|
7511
|
+
const testsDir = path11.join(targetDir, "tests");
|
|
7247
7512
|
return fs9.existsSync(playwrightConfig) && fs9.existsSync(testsDir);
|
|
7248
7513
|
}
|
|
7249
7514
|
|
|
@@ -7287,9 +7552,26 @@ async function setupProject(cliArgs = []) {
|
|
|
7287
7552
|
async function firstTimeSetup(cliSubagents) {
|
|
7288
7553
|
console.log(getBanner());
|
|
7289
7554
|
console.log(chalk2.cyan(" Project Setup\n"));
|
|
7555
|
+
const toolOptions = getToolOptions();
|
|
7556
|
+
const { selectedTool } = await inquirer.prompt([{
|
|
7557
|
+
type: "list",
|
|
7558
|
+
name: "selectedTool",
|
|
7559
|
+
message: "Which AI coding assistant do you use?",
|
|
7560
|
+
choices: toolOptions.map((opt) => ({
|
|
7561
|
+
name: opt.hint ? `${opt.label} - ${chalk2.gray(opt.hint)}` : opt.label,
|
|
7562
|
+
value: opt.value
|
|
7563
|
+
})),
|
|
7564
|
+
default: DEFAULT_TOOL
|
|
7565
|
+
}]);
|
|
7566
|
+
const tool = selectedTool;
|
|
7567
|
+
const toolProfile = getToolProfile(tool);
|
|
7568
|
+
console.log(chalk2.gray(`
|
|
7569
|
+
\u2713 Using ${toolProfile.name}
|
|
7570
|
+
`));
|
|
7290
7571
|
let spinner = ora2("Creating project structure").start();
|
|
7291
|
-
await createProjectStructure();
|
|
7292
|
-
|
|
7572
|
+
await createProjectStructure(tool);
|
|
7573
|
+
const toolDirName = path12.dirname(toolProfile.commandsDir);
|
|
7574
|
+
spinner.succeed(chalk2.green(`Created .bugzy/ and ${toolDirName}/ directories`));
|
|
7293
7575
|
const subagents = {};
|
|
7294
7576
|
if (cliSubagents) {
|
|
7295
7577
|
console.log(chalk2.cyan("\nConfiguring subagents from CLI arguments:\n"));
|
|
@@ -7347,15 +7629,19 @@ async function firstTimeSetup(cliSubagents) {
|
|
|
7347
7629
|
}
|
|
7348
7630
|
}
|
|
7349
7631
|
spinner = ora2("Saving configuration").start();
|
|
7350
|
-
const projectName =
|
|
7351
|
-
const config = createDefaultConfig(projectName);
|
|
7632
|
+
const projectName = path12.basename(process.cwd());
|
|
7633
|
+
const config = createDefaultConfig(projectName, tool);
|
|
7352
7634
|
config.subagents = subagents;
|
|
7353
7635
|
saveConfig(config);
|
|
7354
7636
|
spinner.succeed(chalk2.green("Saved to .bugzy/config.json"));
|
|
7355
|
-
await regenerateAll(subagents);
|
|
7356
|
-
spinner = ora2(
|
|
7357
|
-
|
|
7358
|
-
|
|
7637
|
+
await regenerateAll(subagents, tool);
|
|
7638
|
+
spinner = ora2(`Creating ${toolProfile.memoryFile}`).start();
|
|
7639
|
+
if (tool === "claude-code") {
|
|
7640
|
+
await generateClaudeMd();
|
|
7641
|
+
} else {
|
|
7642
|
+
await generateAgentsMd();
|
|
7643
|
+
}
|
|
7644
|
+
spinner.succeed(chalk2.green(`Created ${toolProfile.memoryFile}`));
|
|
7359
7645
|
spinner = ora2("Updating .gitignore").start();
|
|
7360
7646
|
await updateGitignore();
|
|
7361
7647
|
spinner.succeed(chalk2.green("Updated .gitignore"));
|
|
@@ -7382,11 +7668,38 @@ async function reconfigureProject() {
|
|
|
7382
7668
|
console.error(chalk2.red("Error: Could not load existing configuration"));
|
|
7383
7669
|
process.exit(1);
|
|
7384
7670
|
}
|
|
7671
|
+
const currentTool = getToolFromConfig(existingConfig);
|
|
7672
|
+
const currentToolProfile = getToolProfile(currentTool);
|
|
7385
7673
|
console.log(chalk2.gray("Current configuration:"));
|
|
7674
|
+
console.log(chalk2.gray(` Tool: ${currentToolProfile.name}`));
|
|
7386
7675
|
for (const [role, integration] of Object.entries(existingConfig.subagents)) {
|
|
7387
7676
|
console.log(chalk2.gray(` \u2022 ${role}: ${integration}`));
|
|
7388
7677
|
}
|
|
7389
7678
|
console.log();
|
|
7679
|
+
const toolOptions = getToolOptions();
|
|
7680
|
+
const { changeTool } = await inquirer.prompt([{
|
|
7681
|
+
type: "confirm",
|
|
7682
|
+
name: "changeTool",
|
|
7683
|
+
message: `Keep using ${currentToolProfile.name}?`,
|
|
7684
|
+
default: true
|
|
7685
|
+
}]);
|
|
7686
|
+
let tool = currentTool;
|
|
7687
|
+
if (!changeTool) {
|
|
7688
|
+
const { selectedTool } = await inquirer.prompt([{
|
|
7689
|
+
type: "list",
|
|
7690
|
+
name: "selectedTool",
|
|
7691
|
+
message: "Which AI coding assistant do you want to use?",
|
|
7692
|
+
choices: toolOptions.map((opt) => ({
|
|
7693
|
+
name: opt.hint ? `${opt.label} - ${chalk2.gray(opt.hint)}` : opt.label,
|
|
7694
|
+
value: opt.value
|
|
7695
|
+
})),
|
|
7696
|
+
default: currentTool
|
|
7697
|
+
}]);
|
|
7698
|
+
tool = selectedTool;
|
|
7699
|
+
console.log(chalk2.gray(`
|
|
7700
|
+
\u2713 Switching to ${getToolProfile(tool).name}
|
|
7701
|
+
`));
|
|
7702
|
+
}
|
|
7390
7703
|
const allSubAgents = getAllSubAgents();
|
|
7391
7704
|
const newSubagents = {};
|
|
7392
7705
|
for (const subagent of allSubAgents) {
|
|
@@ -7462,13 +7775,19 @@ async function reconfigureProject() {
|
|
|
7462
7775
|
}
|
|
7463
7776
|
}
|
|
7464
7777
|
let spinner = ora2("Updating configuration").start();
|
|
7778
|
+
existingConfig.tool = tool;
|
|
7465
7779
|
existingConfig.subagents = newSubagents;
|
|
7466
7780
|
await saveConfig(existingConfig);
|
|
7467
7781
|
spinner.succeed(chalk2.green("Updated .bugzy/config.json"));
|
|
7468
|
-
await regenerateAll(newSubagents);
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7782
|
+
await regenerateAll(newSubagents, tool);
|
|
7783
|
+
const toolProfile = getToolProfile(tool);
|
|
7784
|
+
spinner = ora2(`Creating ${toolProfile.memoryFile}`).start();
|
|
7785
|
+
if (tool === "claude-code") {
|
|
7786
|
+
await generateClaudeMd();
|
|
7787
|
+
} else {
|
|
7788
|
+
await generateAgentsMd();
|
|
7789
|
+
}
|
|
7790
|
+
spinner.succeed(chalk2.green(`Created ${toolProfile.memoryFile}`));
|
|
7472
7791
|
console.log(chalk2.green.bold("\n\u2705 Reconfiguration complete!\n"));
|
|
7473
7792
|
console.log(chalk2.yellow("Next steps:"));
|
|
7474
7793
|
console.log(chalk2.white("1. Check .env.example for new required secrets"));
|
|
@@ -7476,23 +7795,52 @@ async function reconfigureProject() {
|
|
|
7476
7795
|
console.log(chalk2.white("3. Run:"), chalk2.cyan("bugzy"));
|
|
7477
7796
|
console.log();
|
|
7478
7797
|
}
|
|
7479
|
-
async function regenerateAll(subagents) {
|
|
7798
|
+
async function regenerateAll(subagents, tool = DEFAULT_TOOL) {
|
|
7799
|
+
const toolProfile = getToolProfile(tool);
|
|
7480
7800
|
let spinner = ora2("Generating task commands").start();
|
|
7481
|
-
await generateCommands(subagents);
|
|
7801
|
+
await generateCommands(subagents, tool);
|
|
7482
7802
|
const taskCount = Object.keys((init_tasks(), __toCommonJS(tasks_exports)).TASK_TEMPLATES).length;
|
|
7483
|
-
spinner.succeed(chalk2.green(`Generated ${taskCount} task commands in .
|
|
7803
|
+
spinner.succeed(chalk2.green(`Generated ${taskCount} task commands in ${toolProfile.commandsDir}/`));
|
|
7484
7804
|
spinner = ora2("Generating subagent configurations").start();
|
|
7485
|
-
await generateAgents(subagents);
|
|
7805
|
+
await generateAgents(subagents, tool);
|
|
7486
7806
|
const subagentCount = Object.keys(subagents).length;
|
|
7487
|
-
spinner.succeed(chalk2.green(`Generated ${subagentCount} subagent configurations in .
|
|
7807
|
+
spinner.succeed(chalk2.green(`Generated ${subagentCount} subagent configurations in ${toolProfile.agentsDir}/`));
|
|
7488
7808
|
spinner = ora2("Generating MCP configuration").start();
|
|
7489
7809
|
const mcpServers = getMCPServersFromSubagents(subagents);
|
|
7490
|
-
await generateMCPConfig(mcpServers);
|
|
7491
|
-
|
|
7810
|
+
await generateMCPConfig(mcpServers, tool);
|
|
7811
|
+
if (toolProfile.mcpFormat === "json") {
|
|
7812
|
+
spinner.succeed(chalk2.green(`Generated ${toolProfile.mcpConfigPath} (${mcpServers.length} servers)`));
|
|
7813
|
+
} else if (toolProfile.mcpFormat === "toml") {
|
|
7814
|
+
spinner.succeed(chalk2.green("MCP configuration ready"));
|
|
7815
|
+
await setupCodexMCP(mcpServers);
|
|
7816
|
+
}
|
|
7492
7817
|
spinner = ora2("Creating environment template").start();
|
|
7493
7818
|
await generateEnvExample(mcpServers);
|
|
7494
7819
|
spinner.succeed(chalk2.green("Created .env.example"));
|
|
7495
7820
|
}
|
|
7821
|
+
async function setupCodexMCP(mcpServers) {
|
|
7822
|
+
const existingServers = await getConfiguredCodexMCPServers();
|
|
7823
|
+
const newServers = mcpServers.filter((s) => !existingServers.includes(s));
|
|
7824
|
+
if (newServers.length === 0) {
|
|
7825
|
+
console.log(chalk2.gray("\n\u2713 All MCP servers already configured"));
|
|
7826
|
+
return;
|
|
7827
|
+
}
|
|
7828
|
+
console.log();
|
|
7829
|
+
for (const serverName of newServers) {
|
|
7830
|
+
const spinner = ora2(`Configuring ${serverName}`).start();
|
|
7831
|
+
try {
|
|
7832
|
+
const { args } = buildCodexMCPCommand(serverName);
|
|
7833
|
+
execSync3(["codex", ...args].join(" "), {
|
|
7834
|
+
stdio: "pipe",
|
|
7835
|
+
env: { ...process.env, CODEX_HOME: path12.join(process.cwd(), ".codex") }
|
|
7836
|
+
});
|
|
7837
|
+
spinner.succeed(chalk2.green(`Configured ${serverName}`));
|
|
7838
|
+
} catch (error) {
|
|
7839
|
+
spinner.fail(chalk2.red(`Failed to configure ${serverName}`));
|
|
7840
|
+
console.error(chalk2.gray(error.message));
|
|
7841
|
+
}
|
|
7842
|
+
}
|
|
7843
|
+
}
|
|
7496
7844
|
|
|
7497
7845
|
// src/cli/index.ts
|
|
7498
7846
|
process.on("uncaughtException", (error) => {
|
|
@@ -7503,9 +7851,9 @@ process.on("unhandledRejection", (reason) => {
|
|
|
7503
7851
|
console.error(chalk3.red("\n\u2717 Error:"), reason?.message || reason);
|
|
7504
7852
|
process.exit(1);
|
|
7505
7853
|
});
|
|
7506
|
-
var __dirname2 =
|
|
7854
|
+
var __dirname2 = dirname7(fileURLToPath2(import.meta.url));
|
|
7507
7855
|
var packageJson = JSON.parse(
|
|
7508
|
-
readFileSync5(
|
|
7856
|
+
readFileSync5(join12(__dirname2, "../../package.json"), "utf-8")
|
|
7509
7857
|
);
|
|
7510
7858
|
if (process.argv.includes("-v") || process.argv.includes("--version")) {
|
|
7511
7859
|
console.log(getBanner());
|