claude-flow-novice 2.3.8 → 2.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/SYNC_USAGE.md +191 -0
- package/config/hooks/post-edit-pipeline.js +49 -0
- package/package.json +18 -9
- package/scripts/create-component.js +200 -0
- package/scripts/subcategorize-agents.js +427 -0
- package/scripts/sync-from-package.js +180 -0
- package/src/cli/hybrid-routing/spawn-workers.js +14 -2
- package/src/index.ts +4 -4
package/SYNC_USAGE.md
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Claude Flow Novice - Sync Guide
|
|
2
|
+
|
|
3
|
+
## Installation & Setup
|
|
4
|
+
|
|
5
|
+
### 1. Install Package
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install claude-flow-novice
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
### 2. Sync Agents, Commands, and Hooks
|
|
12
|
+
|
|
13
|
+
After installation, sync the latest agents, slash commands, and validation hooks to your project:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Sync everything with backup
|
|
17
|
+
npx claude-flow-sync --backup
|
|
18
|
+
|
|
19
|
+
# Or use the longer form
|
|
20
|
+
node node_modules/claude-flow-novice/scripts/sync-from-package.js --backup
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Sync Options
|
|
24
|
+
|
|
25
|
+
### Sync Everything (Recommended for first time)
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx claude-flow-sync --backup
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This syncs:
|
|
32
|
+
- `.claude/agents/` - All agent definitions (94 files)
|
|
33
|
+
- `.claude/commands/` - Slash commands
|
|
34
|
+
- `config/hooks/` - Validation hooks
|
|
35
|
+
|
|
36
|
+
### Selective Sync
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# Sync only agents
|
|
40
|
+
npx claude-flow-sync --agents --backup
|
|
41
|
+
|
|
42
|
+
# Sync only commands
|
|
43
|
+
npx claude-flow-sync --commands --backup
|
|
44
|
+
|
|
45
|
+
# Sync only hooks
|
|
46
|
+
npx claude-flow-sync --hooks --backup
|
|
47
|
+
|
|
48
|
+
# Combine multiple
|
|
49
|
+
npx claude-flow-sync --agents --hooks --backup
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Force Overwrite
|
|
53
|
+
|
|
54
|
+
Use `--force` to overwrite existing files without prompting:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx claude-flow-sync --force --backup
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**⚠️ Warning**: `--force` will overwrite your customizations. Always use `--backup` with `--force`.
|
|
61
|
+
|
|
62
|
+
## Update Workflow
|
|
63
|
+
|
|
64
|
+
### When Package Updates
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
# 1. Update package
|
|
68
|
+
npm update claude-flow-novice
|
|
69
|
+
|
|
70
|
+
# 2. Sync new changes (creates backup automatically)
|
|
71
|
+
npx claude-flow-sync --backup
|
|
72
|
+
|
|
73
|
+
# 3. Review changes
|
|
74
|
+
git diff .claude/ config/
|
|
75
|
+
|
|
76
|
+
# 4. Merge customizations if needed
|
|
77
|
+
# Restore from .backup-YYYY-MM-DD if you need your custom changes
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Customizing Agents/Commands
|
|
81
|
+
|
|
82
|
+
1. **Initial sync**:
|
|
83
|
+
```bash
|
|
84
|
+
npx claude-flow-sync --backup
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
2. **Customize** your local copies in:
|
|
88
|
+
- `.claude/agents/`
|
|
89
|
+
- `.claude/commands/`
|
|
90
|
+
- `config/hooks/`
|
|
91
|
+
|
|
92
|
+
3. **Update from package** (preserves your changes):
|
|
93
|
+
```bash
|
|
94
|
+
# WITHOUT --force, you'll be warned about existing files
|
|
95
|
+
npx claude-flow-sync --backup
|
|
96
|
+
|
|
97
|
+
# Review what changed in the package
|
|
98
|
+
diff -r .claude/agents/ .claude/agents.backup-YYYY-MM-DD/
|
|
99
|
+
|
|
100
|
+
# Manually merge changes you want
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## File Locations After Sync
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
your-project/
|
|
107
|
+
├── .claude/
|
|
108
|
+
│ ├── agents/ # ✅ Synced from package (94 files)
|
|
109
|
+
│ └── commands/ # ✅ Synced from package
|
|
110
|
+
├── config/
|
|
111
|
+
│ └── hooks/ # ✅ Synced from package (13+ files)
|
|
112
|
+
└── node_modules/
|
|
113
|
+
└── claude-flow-novice/
|
|
114
|
+
├── .claude/ # Source (in npm package)
|
|
115
|
+
├── config/ # Source (in npm package)
|
|
116
|
+
└── scripts/ # Source (in npm package)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Backup Management
|
|
120
|
+
|
|
121
|
+
Backups are created as:
|
|
122
|
+
- `.claude/agents.backup-2025-10-17/`
|
|
123
|
+
- `.claude/commands.backup-2025-10-17/`
|
|
124
|
+
- `config/hooks.backup-2025-10-17/`
|
|
125
|
+
|
|
126
|
+
### Restore from Backup
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
# If you need to restore
|
|
130
|
+
rm -rf .claude/agents/
|
|
131
|
+
mv .claude/agents.backup-2025-10-17/ .claude/agents/
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Examples
|
|
135
|
+
|
|
136
|
+
### First-Time Setup
|
|
137
|
+
```bash
|
|
138
|
+
npm install claude-flow-novice
|
|
139
|
+
npx claude-flow-sync --backup
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Regular Updates
|
|
143
|
+
```bash
|
|
144
|
+
npm update claude-flow-novice
|
|
145
|
+
npx claude-flow-sync --backup
|
|
146
|
+
# Review changes with: git diff
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Force Update Everything
|
|
150
|
+
```bash
|
|
151
|
+
npx claude-flow-sync --force --backup
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Update Only Hooks (Get Latest Validators)
|
|
155
|
+
```bash
|
|
156
|
+
npx claude-flow-sync --hooks --force --backup
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## What Gets Synced
|
|
160
|
+
|
|
161
|
+
| Directory | Files | Description |
|
|
162
|
+
|-----------|-------|-------------|
|
|
163
|
+
| `.claude/agents/` | 94 | Agent definitions (optimized, Phase 4) |
|
|
164
|
+
| `.claude/commands/` | 50+ | Slash commands |
|
|
165
|
+
| `config/hooks/` | 13+ | Validation hooks (post-edit, etc.) |
|
|
166
|
+
|
|
167
|
+
## What Doesn't Get Synced
|
|
168
|
+
|
|
169
|
+
- `scripts/` - Only package utilities, not project-specific scripts
|
|
170
|
+
- `readme/` - Package documentation (not project-specific)
|
|
171
|
+
- `src/` - Package source code (not for project use)
|
|
172
|
+
|
|
173
|
+
## Troubleshooting
|
|
174
|
+
|
|
175
|
+
### "Source directory not found"
|
|
176
|
+
Your package might be outdated. Update it:
|
|
177
|
+
```bash
|
|
178
|
+
npm update claude-flow-novice
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### "Destination exists" Warning
|
|
182
|
+
Without `--force`, sync won't overwrite. Use:
|
|
183
|
+
```bash
|
|
184
|
+
npx claude-flow-sync --force --backup
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
### Lost Customizations
|
|
188
|
+
Restore from backup:
|
|
189
|
+
```bash
|
|
190
|
+
mv .claude/agents.backup-YYYY-MM-DD/ .claude/agents/
|
|
191
|
+
```
|
|
@@ -1480,6 +1480,43 @@ class UnifiedPostEditPipeline {
|
|
|
1480
1480
|
}
|
|
1481
1481
|
|
|
1482
1482
|
const projectDir = this.findProjectRoot(filePath);
|
|
1483
|
+
|
|
1484
|
+
// TypeScript incremental type checking (single-file mode)
|
|
1485
|
+
if (language === 'typescript' && tool === 'tsc') {
|
|
1486
|
+
const tsArgs = [...args, '--skipLibCheck', filePath];
|
|
1487
|
+
|
|
1488
|
+
try {
|
|
1489
|
+
const result = await this.runCommand(tool, tsArgs, projectDir);
|
|
1490
|
+
|
|
1491
|
+
// Parse TypeScript error output from both stdout and stderr
|
|
1492
|
+
const allOutput = result.stdout + result.stderr;
|
|
1493
|
+
const errorLines = allOutput.split('\n').filter(line => line.includes('error TS'));
|
|
1494
|
+
const errorCount = errorLines.length;
|
|
1495
|
+
|
|
1496
|
+
return {
|
|
1497
|
+
success: result.code === 0 && errorCount === 0,
|
|
1498
|
+
message: result.code === 0 ? 'TypeScript compilation passed' : `${errorCount} TypeScript error(s)`,
|
|
1499
|
+
output: allOutput,
|
|
1500
|
+
errors: errorCount > 0 ? errorLines.join('\n') : '',
|
|
1501
|
+
errorCount,
|
|
1502
|
+
errorLines: errorLines.slice(0, 10), // First 10 errors for feedback
|
|
1503
|
+
wasmAccelerated
|
|
1504
|
+
};
|
|
1505
|
+
} catch (error) {
|
|
1506
|
+
// Handle TypeScript compiler crashes gracefully
|
|
1507
|
+
return {
|
|
1508
|
+
success: false,
|
|
1509
|
+
message: 'TypeScript compiler error',
|
|
1510
|
+
output: error.message || error.stderr || '',
|
|
1511
|
+
errors: error.message || 'TypeScript compilation failed',
|
|
1512
|
+
errorCount: 1,
|
|
1513
|
+
errorLines: [(error.message || 'Unknown compiler error')],
|
|
1514
|
+
wasmAccelerated
|
|
1515
|
+
};
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
// Standard type checking for other languages
|
|
1483
1520
|
const result = await this.runCommand(tool, args, projectDir);
|
|
1484
1521
|
|
|
1485
1522
|
return {
|
|
@@ -2126,6 +2163,18 @@ class UnifiedPostEditPipeline {
|
|
|
2126
2163
|
if (!results.steps.typeCheck.success) {
|
|
2127
2164
|
results.summary.errors.push(`Type errors in ${path.basename(filePath)}`);
|
|
2128
2165
|
results.summary.success = false;
|
|
2166
|
+
|
|
2167
|
+
// Send TYPE_ERROR feedback to agent
|
|
2168
|
+
await this.sendAgentFeedback({
|
|
2169
|
+
type: 'TYPE_ERROR',
|
|
2170
|
+
file: filePath,
|
|
2171
|
+
severity: 'error',
|
|
2172
|
+
language,
|
|
2173
|
+
errorCount: results.steps.typeCheck.errorCount || 0,
|
|
2174
|
+
errorLines: results.steps.typeCheck.errorLines || [],
|
|
2175
|
+
errors: results.steps.typeCheck.errors,
|
|
2176
|
+
message: `${results.steps.typeCheck.errorCount || 'Unknown'} TypeScript error(s) in ${path.basename(filePath)}`
|
|
2177
|
+
});
|
|
2129
2178
|
}
|
|
2130
2179
|
|
|
2131
2180
|
// Step 4: Rust Quality Enforcement (if Rust and strict mode)
|
package/package.json
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow-novice",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "AI Agent Orchestration CLI",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"bin": {
|
|
7
|
-
"claude-flow-novice": "./src/cli/index.ts"
|
|
7
|
+
"claude-flow-novice": "./src/cli/index.ts",
|
|
8
|
+
"claude-flow-sync": "./scripts/sync-from-package.js"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|
|
10
11
|
"src",
|
|
11
12
|
"README.md",
|
|
12
13
|
"CHANGELOG.md",
|
|
13
14
|
"LICENSE",
|
|
15
|
+
"SYNC_USAGE.md",
|
|
14
16
|
"config",
|
|
15
17
|
"scripts",
|
|
16
18
|
".claude",
|
|
@@ -21,6 +23,8 @@
|
|
|
21
23
|
"clean": "rimraf dist",
|
|
22
24
|
"lint": "eslint . --ext .ts",
|
|
23
25
|
"typecheck": "tsc --noEmit",
|
|
26
|
+
"type-coverage": "type-coverage --detail --ignore-files 'src/__tests__/**' --ignore-files '**/*.test.ts'",
|
|
27
|
+
"type-coverage:ci": "type-coverage --at-least 80 --ignore-files 'src/__tests__/**' --ignore-files '**/*.test.ts'",
|
|
24
28
|
"test": "jest",
|
|
25
29
|
"test:coverage": "jest --coverage",
|
|
26
30
|
"prepublish-checks": "node scripts/prepublish-checks.js",
|
|
@@ -28,7 +32,8 @@
|
|
|
28
32
|
"security-scan": "snyk test && npm audit --audit-level=high",
|
|
29
33
|
"bundle-size-check": "bundlesize",
|
|
30
34
|
"smoke-test": "npm pack && node scripts/smoke-test.js",
|
|
31
|
-
"changelog": "standard-version"
|
|
35
|
+
"changelog": "standard-version",
|
|
36
|
+
"create:component": "node scripts/create-component.js"
|
|
32
37
|
},
|
|
33
38
|
"keywords": [
|
|
34
39
|
"ai",
|
|
@@ -53,15 +58,19 @@
|
|
|
53
58
|
},
|
|
54
59
|
"devDependencies": {
|
|
55
60
|
"@types/node": "^20.0.0",
|
|
56
|
-
"
|
|
57
|
-
"jest": "^29.0.0",
|
|
61
|
+
"bundlesize": "^0.18.1",
|
|
58
62
|
"eslint": "^8.0.0",
|
|
59
|
-
"
|
|
63
|
+
"husky": "^8.0.0",
|
|
64
|
+
"jest": "^29.0.0",
|
|
60
65
|
"rimraf": "^5.0.0",
|
|
61
|
-
"
|
|
62
|
-
"snyk": "^1.0.0",
|
|
66
|
+
"rollup": "^3.0.0",
|
|
63
67
|
"semantic-release": "^21.0.0",
|
|
68
|
+
"snyk": "^1.0.0",
|
|
64
69
|
"standard-version": "^9.0.0",
|
|
65
|
-
"
|
|
70
|
+
"type-coverage": "^2.29.7",
|
|
71
|
+
"typescript": "^5.9.3"
|
|
72
|
+
},
|
|
73
|
+
"dependencies": {
|
|
74
|
+
"ioredis": "^5.8.1"
|
|
66
75
|
}
|
|
67
76
|
}
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Component Template Generator
|
|
5
|
+
* Creates TypeScript components with proper type declarations and tests
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* node scripts/create-component.js <ComponentName> <directory>
|
|
9
|
+
*
|
|
10
|
+
* Example:
|
|
11
|
+
* node scripts/create-component.js SwarmCoordinator src/coordination
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import fs from 'fs';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
|
|
18
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
19
|
+
const __dirname = path.dirname(__filename);
|
|
20
|
+
|
|
21
|
+
const [, , componentName, componentDir] = process.argv;
|
|
22
|
+
|
|
23
|
+
if (!componentName || !componentDir) {
|
|
24
|
+
console.log(`
|
|
25
|
+
🔧 Component Template Generator
|
|
26
|
+
|
|
27
|
+
Usage: node scripts/create-component.js <ComponentName> <directory>
|
|
28
|
+
|
|
29
|
+
Arguments:
|
|
30
|
+
ComponentName Name of the component (PascalCase)
|
|
31
|
+
directory Target directory (e.g., src/coordination)
|
|
32
|
+
|
|
33
|
+
Examples:
|
|
34
|
+
node scripts/create-component.js SwarmCoordinator src/coordination
|
|
35
|
+
node scripts/create-component.js TaskValidator src/validation
|
|
36
|
+
node scripts/create-component.js RedisClient src/services
|
|
37
|
+
|
|
38
|
+
Generated files:
|
|
39
|
+
✅ <directory>/<ComponentName>.ts - Main implementation
|
|
40
|
+
✅ <directory>/<ComponentName>.test.ts - Test file with basic setup
|
|
41
|
+
✅ <directory>/types.ts - Type definitions (if doesn't exist)
|
|
42
|
+
`);
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const projectRoot = path.resolve(__dirname, '..');
|
|
47
|
+
|
|
48
|
+
// Validate component name (PascalCase)
|
|
49
|
+
if (!/^[A-Z][a-zA-Z0-9]*$/.test(componentName)) {
|
|
50
|
+
console.error(`❌ Error: Component name must be PascalCase (e.g., SwarmCoordinator, not swarm-coordinator)`);
|
|
51
|
+
process.exit(1);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Create directory if it doesn't exist
|
|
55
|
+
const targetDir = path.join(projectRoot, componentDir);
|
|
56
|
+
if (!fs.existsSync(targetDir)) {
|
|
57
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
58
|
+
console.log(`📁 Created directory: ${componentDir}/`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Component file template
|
|
62
|
+
const componentTemplate = `/**
|
|
63
|
+
* ${componentName}
|
|
64
|
+
*
|
|
65
|
+
* TODO: Add component description
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
export interface ${componentName}Options {
|
|
69
|
+
// TODO: Define configuration options
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export class ${componentName} {
|
|
73
|
+
private options: ${componentName}Options;
|
|
74
|
+
|
|
75
|
+
constructor(options: ${componentName}Options) {
|
|
76
|
+
this.options = options;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// TODO: Implement methods
|
|
80
|
+
async initialize(): Promise<void> {
|
|
81
|
+
// Initialization logic
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async execute(): Promise<void> {
|
|
85
|
+
// Main execution logic
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async cleanup(): Promise<void> {
|
|
89
|
+
// Cleanup logic
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
// Test file template
|
|
95
|
+
const testTemplate = `import { describe, it, expect, beforeEach, afterEach } from '@jest/globals';
|
|
96
|
+
import { ${componentName} } from './${componentName}';
|
|
97
|
+
|
|
98
|
+
describe('${componentName}', () => {
|
|
99
|
+
let component: ${componentName};
|
|
100
|
+
|
|
101
|
+
beforeEach(() => {
|
|
102
|
+
component = new ${componentName}({
|
|
103
|
+
// TODO: Add test configuration
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
afterEach(async () => {
|
|
108
|
+
await component.cleanup();
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('initialization', () => {
|
|
112
|
+
it('should initialize successfully', async () => {
|
|
113
|
+
await component.initialize();
|
|
114
|
+
// TODO: Add assertions
|
|
115
|
+
expect(component).toBeDefined();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe('execution', () => {
|
|
120
|
+
it('should execute successfully', async () => {
|
|
121
|
+
await component.initialize();
|
|
122
|
+
await component.execute();
|
|
123
|
+
// TODO: Add assertions
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
describe('error handling', () => {
|
|
128
|
+
it('should handle errors gracefully', async () => {
|
|
129
|
+
// TODO: Test error scenarios
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
`;
|
|
134
|
+
|
|
135
|
+
// Types file template (only create if doesn't exist)
|
|
136
|
+
const typesTemplate = `/**
|
|
137
|
+
* Type definitions for ${componentDir}
|
|
138
|
+
*/
|
|
139
|
+
|
|
140
|
+
export interface BaseOptions {
|
|
141
|
+
enabled?: boolean;
|
|
142
|
+
debug?: boolean;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Add shared types here
|
|
146
|
+
`;
|
|
147
|
+
|
|
148
|
+
// Write component file
|
|
149
|
+
const componentPath = path.join(targetDir, `${componentName}.ts`);
|
|
150
|
+
if (fs.existsSync(componentPath)) {
|
|
151
|
+
console.error(`❌ Error: Component file already exists: ${componentPath}`);
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
fs.writeFileSync(componentPath, componentTemplate);
|
|
155
|
+
console.log(`✅ Created: ${path.relative(projectRoot, componentPath)}`);
|
|
156
|
+
|
|
157
|
+
// Write test file
|
|
158
|
+
const testPath = path.join(targetDir, `${componentName}.test.ts`);
|
|
159
|
+
if (fs.existsSync(testPath)) {
|
|
160
|
+
console.warn(`⚠️ Warning: Test file already exists: ${testPath} (skipping)`);
|
|
161
|
+
} else {
|
|
162
|
+
fs.writeFileSync(testPath, testTemplate);
|
|
163
|
+
console.log(`✅ Created: ${path.relative(projectRoot, testPath)}`);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Create types file if doesn't exist
|
|
167
|
+
const typesPath = path.join(targetDir, 'types.ts');
|
|
168
|
+
if (!fs.existsSync(typesPath)) {
|
|
169
|
+
fs.writeFileSync(typesPath, typesTemplate);
|
|
170
|
+
console.log(`✅ Created: ${path.relative(projectRoot, typesPath)}`);
|
|
171
|
+
} else {
|
|
172
|
+
console.log(`ℹ️ Types file exists: ${path.relative(projectRoot, typesPath)} (not modified)`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Create index.ts barrel export if doesn't exist
|
|
176
|
+
const indexPath = path.join(targetDir, 'index.ts');
|
|
177
|
+
const exportLine = `export * from './${componentName}';\n`;
|
|
178
|
+
|
|
179
|
+
if (fs.existsSync(indexPath)) {
|
|
180
|
+
const content = fs.readFileSync(indexPath, 'utf8');
|
|
181
|
+
if (!content.includes(`from './${componentName}'`)) {
|
|
182
|
+
fs.appendFileSync(indexPath, exportLine);
|
|
183
|
+
console.log(`✅ Added export to: ${path.relative(projectRoot, indexPath)}`);
|
|
184
|
+
} else {
|
|
185
|
+
console.log(`ℹ️ Export already exists in: ${path.relative(projectRoot, indexPath)}`);
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
fs.writeFileSync(indexPath, `export * from './types';\n${exportLine}`);
|
|
189
|
+
console.log(`✅ Created: ${path.relative(projectRoot, indexPath)}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
console.log(`
|
|
193
|
+
✨ Component generated successfully!
|
|
194
|
+
|
|
195
|
+
Next steps:
|
|
196
|
+
1. Implement ${componentName} logic in ${componentPath}
|
|
197
|
+
2. Write tests in ${testPath}
|
|
198
|
+
3. Run tests: npm test -- ${componentName}
|
|
199
|
+
4. Run type check: npm run typecheck
|
|
200
|
+
`);
|
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create subcategories within each main agent category
|
|
5
|
+
* Provides finer-grained organization for easier browsing
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const AGENTS_DIR = path.join(__dirname, '../agents');
|
|
12
|
+
|
|
13
|
+
// Subcategory definitions for each main category
|
|
14
|
+
const SUBCATEGORIES = {
|
|
15
|
+
'development-engineering': {
|
|
16
|
+
'backend': {
|
|
17
|
+
keywords: ['backend', 'api', 'rest', 'graphql', 'server', 'node', 'django', 'flask', 'express', 'fastapi'],
|
|
18
|
+
description: 'Backend development, APIs, server-side programming'
|
|
19
|
+
},
|
|
20
|
+
'frontend': {
|
|
21
|
+
keywords: ['frontend', 'react', 'angular', 'vue', 'ui', 'javascript', 'typescript', 'css', 'html', 'web-ui'],
|
|
22
|
+
description: 'Frontend frameworks, UI development, client-side'
|
|
23
|
+
},
|
|
24
|
+
'mobile': {
|
|
25
|
+
keywords: ['mobile', 'ios', 'android', 'react-native', 'flutter', 'swift', 'kotlin'],
|
|
26
|
+
description: 'Mobile app development (iOS, Android)'
|
|
27
|
+
},
|
|
28
|
+
'devops': {
|
|
29
|
+
keywords: ['devops', 'docker', 'kubernetes', 'ci-cd', 'cicd', 'deployment', 'container', 'gitops', 'argocd', 'flux', 'jenkins'],
|
|
30
|
+
description: 'DevOps, CI/CD, containerization, orchestration'
|
|
31
|
+
},
|
|
32
|
+
'testing': {
|
|
33
|
+
keywords: ['test', 'qa', 'quality', 'acceptance', 'cypress', 'jest', 'playwright', 'e2e', 'integration-test', 'unit-test', 'fuzz'],
|
|
34
|
+
description: 'Testing, QA, quality assurance, test automation'
|
|
35
|
+
},
|
|
36
|
+
'database': {
|
|
37
|
+
keywords: ['database', 'sql', 'nosql', 'postgres', 'mysql', 'mongodb', 'redis', 'data-model'],
|
|
38
|
+
description: 'Database design, SQL, NoSQL, data modeling'
|
|
39
|
+
},
|
|
40
|
+
'architecture': {
|
|
41
|
+
keywords: ['architect', 'architecture', 'design-pattern', 'microservices', 'system-design', 'scalability'],
|
|
42
|
+
description: 'Software architecture, system design, patterns'
|
|
43
|
+
},
|
|
44
|
+
'integration': {
|
|
45
|
+
keywords: ['integration', 'api-integration', 'third-party', 'webhook', 'payment-integration', 'oauth'],
|
|
46
|
+
description: 'API integration, third-party services, webhooks'
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
'industry-specific': {
|
|
51
|
+
'healthcare': {
|
|
52
|
+
keywords: ['health', 'medical', 'clinical', 'patient', 'doctor', 'hospital', 'telemedicine', 'pharmaceutical'],
|
|
53
|
+
description: 'Healthcare, medical, clinical systems'
|
|
54
|
+
},
|
|
55
|
+
'finance': {
|
|
56
|
+
keywords: ['finance', 'banking', 'fintech', 'trading', 'investment', 'accounting', 'ledger', 'financial'],
|
|
57
|
+
description: 'Finance, banking, fintech, trading'
|
|
58
|
+
},
|
|
59
|
+
'legal': {
|
|
60
|
+
keywords: ['legal', 'law', 'attorney', 'court', 'litigation', 'contract', 'compliance-legal'],
|
|
61
|
+
description: 'Legal services, law firms, compliance'
|
|
62
|
+
},
|
|
63
|
+
'education': {
|
|
64
|
+
keywords: ['education', 'learning', 'student', 'teacher', 'academic', 'e-learning', 'training', 'course'],
|
|
65
|
+
description: 'Education, e-learning, academic systems'
|
|
66
|
+
},
|
|
67
|
+
'retail': {
|
|
68
|
+
keywords: ['retail', 'e-commerce', 'shop', 'store', 'pos', 'inventory', 'product', 'catalog'],
|
|
69
|
+
description: 'Retail, e-commerce, point-of-sale'
|
|
70
|
+
},
|
|
71
|
+
'manufacturing': {
|
|
72
|
+
keywords: ['manufactur', 'production', 'factory', 'supply-chain', 'logistics', 'warehouse', 'industrial'],
|
|
73
|
+
description: 'Manufacturing, production, supply chain'
|
|
74
|
+
},
|
|
75
|
+
'entertainment': {
|
|
76
|
+
keywords: ['entertainment', 'media', 'gaming', 'sports', 'music', 'video', 'streaming', 'content'],
|
|
77
|
+
description: 'Entertainment, media, gaming, sports'
|
|
78
|
+
},
|
|
79
|
+
'other': {
|
|
80
|
+
keywords: ['real-estate', 'hospitality', 'tourism', 'energy', 'utilities', 'telecom', 'insurance', 'nonprofit'],
|
|
81
|
+
description: 'Other industries (real estate, hospitality, etc.)'
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
'ai-ml-automation': {
|
|
86
|
+
'machine-learning': {
|
|
87
|
+
keywords: ['machine-learning', 'ml', 'supervised', 'unsupervised', 'classification', 'regression', 'scikit'],
|
|
88
|
+
description: 'Traditional machine learning, classification, regression'
|
|
89
|
+
},
|
|
90
|
+
'deep-learning': {
|
|
91
|
+
keywords: ['deep-learning', 'neural', 'tensorflow', 'pytorch', 'keras', 'cnn', 'rnn', 'transformer'],
|
|
92
|
+
description: 'Deep learning, neural networks, frameworks'
|
|
93
|
+
},
|
|
94
|
+
'nlp': {
|
|
95
|
+
keywords: ['nlp', 'natural-language', 'text', 'sentiment', 'chatbot', 'language-model', 'tokeniz'],
|
|
96
|
+
description: 'Natural language processing, text analysis'
|
|
97
|
+
},
|
|
98
|
+
'computer-vision': {
|
|
99
|
+
keywords: ['vision', 'image', 'video', 'object-detection', 'facial', 'ocr', 'recognition'],
|
|
100
|
+
description: 'Computer vision, image processing, object detection'
|
|
101
|
+
},
|
|
102
|
+
'mlops': {
|
|
103
|
+
keywords: ['mlops', 'model-deployment', 'training-pipeline', 'experiment-tracking', 'model-serving'],
|
|
104
|
+
description: 'MLOps, model deployment, training pipelines'
|
|
105
|
+
},
|
|
106
|
+
'automation': {
|
|
107
|
+
keywords: ['automation', 'intelligent-automation', 'workflow', 'orchestration', 'agent-based'],
|
|
108
|
+
description: 'Intelligent automation, workflow automation'
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
'business-operations': {
|
|
113
|
+
'strategy': {
|
|
114
|
+
keywords: ['strategy', 'strategic', 'planning', 'competitive', 'positioning', 'vision'],
|
|
115
|
+
description: 'Business strategy, strategic planning'
|
|
116
|
+
},
|
|
117
|
+
'growth': {
|
|
118
|
+
keywords: ['growth', 'scaling', 'expansion', 'market-expansion', 'growth-hacking'],
|
|
119
|
+
description: 'Business growth, scaling, expansion'
|
|
120
|
+
},
|
|
121
|
+
'revenue': {
|
|
122
|
+
keywords: ['revenue', 'sales', 'monetization', 'pricing', 'billing', 'subscription'],
|
|
123
|
+
description: 'Revenue optimization, sales, monetization'
|
|
124
|
+
},
|
|
125
|
+
'customer': {
|
|
126
|
+
keywords: ['customer', 'client', 'user-experience', 'crm', 'support', 'journey', 'satisfaction'],
|
|
127
|
+
description: 'Customer experience, CRM, support'
|
|
128
|
+
},
|
|
129
|
+
'operations': {
|
|
130
|
+
keywords: ['operations', 'operational', 'process', 'workflow', 'efficiency', 'optimization'],
|
|
131
|
+
description: 'Operations management, process optimization'
|
|
132
|
+
},
|
|
133
|
+
'leadership': {
|
|
134
|
+
keywords: ['leadership', 'management', 'executive', 'team-building', 'organizational'],
|
|
135
|
+
description: 'Leadership, management, organizational development'
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
'data-analytics': {
|
|
140
|
+
'business-intelligence': {
|
|
141
|
+
keywords: ['business-intelligence', 'bi', 'dashboard', 'reporting', 'kpi', 'metrics'],
|
|
142
|
+
description: 'Business intelligence, dashboards, reporting'
|
|
143
|
+
},
|
|
144
|
+
'data-engineering': {
|
|
145
|
+
keywords: ['etl', 'elt', 'pipeline', 'data-pipeline', 'warehouse', 'lake', 'ingestion'],
|
|
146
|
+
description: 'Data engineering, ETL/ELT, data pipelines'
|
|
147
|
+
},
|
|
148
|
+
'analytics': {
|
|
149
|
+
keywords: ['analytics', 'analysis', 'insights', 'statistical', 'predictive', 'prescriptive'],
|
|
150
|
+
description: 'Data analytics, statistical analysis, insights'
|
|
151
|
+
},
|
|
152
|
+
'forecasting': {
|
|
153
|
+
keywords: ['forecast', 'prediction', 'time-series', 'trend', 'anomaly-detection'],
|
|
154
|
+
description: 'Forecasting, time-series analysis, predictions'
|
|
155
|
+
},
|
|
156
|
+
'visualization': {
|
|
157
|
+
keywords: ['visualization', 'chart', 'graph', 'tableau', 'power-bi', 'data-viz'],
|
|
158
|
+
description: 'Data visualization, charts, dashboards'
|
|
159
|
+
}
|
|
160
|
+
},
|
|
161
|
+
|
|
162
|
+
'personal-professional': {
|
|
163
|
+
'career': {
|
|
164
|
+
keywords: ['career', 'job', 'interview', 'resume', 'job-search', 'promotion', 'transition'],
|
|
165
|
+
description: 'Career development, job search, interviews'
|
|
166
|
+
},
|
|
167
|
+
'leadership': {
|
|
168
|
+
keywords: ['leadership', 'leader', 'management', 'executive', 'mentoring', 'coaching'],
|
|
169
|
+
description: 'Leadership development, coaching, mentoring'
|
|
170
|
+
},
|
|
171
|
+
'productivity': {
|
|
172
|
+
keywords: ['productivity', 'time-management', 'efficiency', 'goal', 'planning', 'organization'],
|
|
173
|
+
description: 'Productivity, time management, goal setting'
|
|
174
|
+
},
|
|
175
|
+
'communication': {
|
|
176
|
+
keywords: ['communication', 'presentation', 'public-speaking', 'writing', 'listening', 'feedback'],
|
|
177
|
+
description: 'Communication skills, presentations, feedback'
|
|
178
|
+
},
|
|
179
|
+
'wellness': {
|
|
180
|
+
keywords: ['wellness', 'stress', 'work-life', 'balance', 'mindfulness', 'mental-health', 'emotional'],
|
|
181
|
+
description: 'Wellness, work-life balance, mental health'
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
'security-compliance': {
|
|
186
|
+
'cybersecurity': {
|
|
187
|
+
keywords: ['cybersecurity', 'security', 'threat', 'vulnerability', 'penetration', 'firewall', 'encryption'],
|
|
188
|
+
description: 'Cybersecurity, threat analysis, penetration testing'
|
|
189
|
+
},
|
|
190
|
+
'compliance': {
|
|
191
|
+
keywords: ['compliance', 'regulatory', 'audit', 'gdpr', 'hipaa', 'sox', 'pci', 'iso'],
|
|
192
|
+
description: 'Compliance, regulatory requirements, auditing'
|
|
193
|
+
},
|
|
194
|
+
'privacy': {
|
|
195
|
+
keywords: ['privacy', 'data-privacy', 'gdpr', 'personal-data', 'consent', 'anonymization'],
|
|
196
|
+
description: 'Data privacy, GDPR, personal data protection'
|
|
197
|
+
},
|
|
198
|
+
'access-control': {
|
|
199
|
+
keywords: ['access-control', 'authentication', 'authorization', 'identity', 'zero-trust', 'iam'],
|
|
200
|
+
description: 'Access control, authentication, identity management'
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
'payment-financial': {
|
|
205
|
+
'payment-gateways': {
|
|
206
|
+
keywords: ['stripe', 'paypal', 'square', 'braintree', 'checkout', 'payment-gateway', 'merchant'],
|
|
207
|
+
description: 'Payment gateways (Stripe, PayPal, Square, etc.)'
|
|
208
|
+
},
|
|
209
|
+
'bnpl': {
|
|
210
|
+
keywords: ['bnpl', 'afterpay', 'klarna', 'affirm', 'installment', 'buy-now-pay-later'],
|
|
211
|
+
description: 'Buy-now-pay-later, installment payments'
|
|
212
|
+
},
|
|
213
|
+
'cryptocurrency': {
|
|
214
|
+
keywords: ['crypto', 'bitcoin', 'ethereum', 'blockchain', 'wallet', 'web3'],
|
|
215
|
+
description: 'Cryptocurrency, blockchain, Web3 payments'
|
|
216
|
+
},
|
|
217
|
+
'billing': {
|
|
218
|
+
keywords: ['billing', 'invoice', 'subscription', 'recurring', 'pricing'],
|
|
219
|
+
description: 'Billing systems, invoicing, subscriptions'
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Extract YAML frontmatter from markdown file
|
|
226
|
+
*/
|
|
227
|
+
function extractFrontmatter(content) {
|
|
228
|
+
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
229
|
+
if (!match) return null;
|
|
230
|
+
|
|
231
|
+
const frontmatter = {};
|
|
232
|
+
const lines = match[1].split('\n');
|
|
233
|
+
|
|
234
|
+
for (const line of lines) {
|
|
235
|
+
const colonIndex = line.indexOf(':');
|
|
236
|
+
if (colonIndex === -1) continue;
|
|
237
|
+
|
|
238
|
+
const key = line.substring(0, colonIndex).trim();
|
|
239
|
+
const value = line.substring(colonIndex + 1).trim();
|
|
240
|
+
frontmatter[key] = value;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return frontmatter;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Categorize agent into subcategory
|
|
248
|
+
*/
|
|
249
|
+
function subcategorizeAgent(filename, content, mainCategory) {
|
|
250
|
+
const subcategories = SUBCATEGORIES[mainCategory];
|
|
251
|
+
if (!subcategories) return null;
|
|
252
|
+
|
|
253
|
+
const frontmatter = extractFrontmatter(content);
|
|
254
|
+
const searchText = (filename + ' ' + (frontmatter?.name || '') + ' ' + (frontmatter?.description || '')).toLowerCase();
|
|
255
|
+
|
|
256
|
+
let bestSubcategory = null;
|
|
257
|
+
let bestScore = 0;
|
|
258
|
+
|
|
259
|
+
for (const [subcategory, config] of Object.entries(subcategories)) {
|
|
260
|
+
let score = 0;
|
|
261
|
+
for (const keyword of config.keywords) {
|
|
262
|
+
if (searchText.includes(keyword.toLowerCase())) {
|
|
263
|
+
score++;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (score > bestScore) {
|
|
268
|
+
bestScore = score;
|
|
269
|
+
bestSubcategory = subcategory;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Default to first subcategory or 'other' if no match
|
|
274
|
+
if (!bestSubcategory) {
|
|
275
|
+
bestSubcategory = subcategories.other ? 'other' : Object.keys(subcategories)[0];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
return bestSubcategory;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Process a single main category
|
|
283
|
+
*/
|
|
284
|
+
function processCategory(mainCategory) {
|
|
285
|
+
const categoryDir = path.join(AGENTS_DIR, mainCategory);
|
|
286
|
+
if (!fs.existsSync(categoryDir)) {
|
|
287
|
+
console.log(`⏭️ Skipping ${mainCategory} (not found)`);
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
console.log(`\n📂 Processing ${mainCategory}...`);
|
|
292
|
+
|
|
293
|
+
// Read agent files
|
|
294
|
+
const files = fs.readdirSync(categoryDir)
|
|
295
|
+
.filter(f => f.endsWith('.md') && f !== 'INDEX.md');
|
|
296
|
+
|
|
297
|
+
if (files.length === 0) {
|
|
298
|
+
console.log(` No agents found in ${mainCategory}`);
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
console.log(` Found ${files.length} agents`);
|
|
303
|
+
|
|
304
|
+
// Categorize into subcategories
|
|
305
|
+
const subcategorization = {};
|
|
306
|
+
const subcategoryConfigs = SUBCATEGORIES[mainCategory];
|
|
307
|
+
|
|
308
|
+
for (const subcategory of Object.keys(subcategoryConfigs)) {
|
|
309
|
+
subcategorization[subcategory] = [];
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
for (const file of files) {
|
|
313
|
+
const filePath = path.join(categoryDir, file);
|
|
314
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
315
|
+
const subcategory = subcategorizeAgent(file, content, mainCategory);
|
|
316
|
+
|
|
317
|
+
if (subcategory && subcategorization[subcategory]) {
|
|
318
|
+
subcategorization[subcategory].push(file);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// Display subcategorization
|
|
323
|
+
console.log(`\n Subcategories:`);
|
|
324
|
+
for (const [subcategory, files] of Object.entries(subcategorization)) {
|
|
325
|
+
if (files.length > 0) {
|
|
326
|
+
console.log(` ${subcategory}: ${files.length} agents`);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Create subdirectories and move files
|
|
331
|
+
for (const [subcategory, config] of Object.entries(subcategoryConfigs)) {
|
|
332
|
+
const subcategoryDir = path.join(categoryDir, subcategory);
|
|
333
|
+
const filesToMove = subcategorization[subcategory];
|
|
334
|
+
|
|
335
|
+
if (filesToMove.length === 0) continue;
|
|
336
|
+
|
|
337
|
+
// Create directory
|
|
338
|
+
if (!fs.existsSync(subcategoryDir)) {
|
|
339
|
+
fs.mkdirSync(subcategoryDir, { recursive: true });
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// Move files
|
|
343
|
+
for (const file of filesToMove) {
|
|
344
|
+
const src = path.join(categoryDir, file);
|
|
345
|
+
const dest = path.join(subcategoryDir, file);
|
|
346
|
+
fs.renameSync(src, dest);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Create subcategory index
|
|
350
|
+
const indexContent = `# ${subcategory.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')}
|
|
351
|
+
|
|
352
|
+
**Description:** ${config.description}
|
|
353
|
+
**Agent Count:** ${filesToMove.length}
|
|
354
|
+
|
|
355
|
+
## Available Agents
|
|
356
|
+
|
|
357
|
+
${filesToMove.sort().map(f => `- [${f.replace('.md', '')}](./${f})`).join('\n')}
|
|
358
|
+
`;
|
|
359
|
+
|
|
360
|
+
fs.writeFileSync(path.join(subcategoryDir, 'INDEX.md'), indexContent);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Update main category index
|
|
364
|
+
const mainIndexContent = `# ${mainCategory.split('-').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ')}
|
|
365
|
+
|
|
366
|
+
**Total Agents:** ${files.length}
|
|
367
|
+
|
|
368
|
+
## Subcategories
|
|
369
|
+
|
|
370
|
+
${Object.entries(subcategorization)
|
|
371
|
+
.filter(([_, files]) => files.length > 0)
|
|
372
|
+
.sort((a, b) => b[1].length - a[1].length)
|
|
373
|
+
.map(([subcat, files]) => {
|
|
374
|
+
const config = subcategoryConfigs[subcat];
|
|
375
|
+
return `### [${subcat}](${subcat}/INDEX.md) (${files.length} agents)
|
|
376
|
+
|
|
377
|
+
${config.description}
|
|
378
|
+
`;
|
|
379
|
+
}).join('\n')}
|
|
380
|
+
|
|
381
|
+
## Quick Navigation
|
|
382
|
+
|
|
383
|
+
${Object.entries(subcategorization)
|
|
384
|
+
.filter(([_, files]) => files.length > 0)
|
|
385
|
+
.map(([subcat, files]) => `- [${subcat}](${subcat}/INDEX.md) - ${files.length} agents`)
|
|
386
|
+
.join('\n')}
|
|
387
|
+
`;
|
|
388
|
+
|
|
389
|
+
fs.writeFileSync(path.join(categoryDir, 'INDEX.md'), mainIndexContent);
|
|
390
|
+
|
|
391
|
+
return {
|
|
392
|
+
category: mainCategory,
|
|
393
|
+
totalAgents: files.length,
|
|
394
|
+
subcategories: Object.fromEntries(
|
|
395
|
+
Object.entries(subcategorization).filter(([_, files]) => files.length > 0)
|
|
396
|
+
)
|
|
397
|
+
};
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Main subcategorization process
|
|
402
|
+
*/
|
|
403
|
+
async function subcategorizeAgents() {
|
|
404
|
+
console.log('🔍 Subcategorizing agents within each main category...\n');
|
|
405
|
+
|
|
406
|
+
const results = {};
|
|
407
|
+
|
|
408
|
+
for (const mainCategory of Object.keys(SUBCATEGORIES)) {
|
|
409
|
+
const result = processCategory(mainCategory);
|
|
410
|
+
if (result) {
|
|
411
|
+
results[mainCategory] = result;
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
console.log('\n\n✅ Subcategorization complete!\n');
|
|
416
|
+
|
|
417
|
+
// Generate summary
|
|
418
|
+
console.log('📊 Summary by Main Category:\n');
|
|
419
|
+
for (const [category, data] of Object.entries(results)) {
|
|
420
|
+
console.log(`${category}: ${data.totalAgents} agents in ${Object.keys(data.subcategories).length} subcategories`);
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
console.log('\n✨ Done!\n');
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// Run
|
|
427
|
+
subcategorizeAgents().catch(console.error);
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Sync agents, commands, and hooks from npm package to local project
|
|
4
|
+
* Usage: npx claude-flow-novice sync [--force] [--backup] [--agents] [--commands] [--hooks]
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const { execSync } = require('child_process');
|
|
10
|
+
|
|
11
|
+
const args = process.argv.slice(2);
|
|
12
|
+
const flags = {
|
|
13
|
+
force: args.includes('--force'),
|
|
14
|
+
backup: args.includes('--backup'),
|
|
15
|
+
agents: args.includes('--agents') || args.length === 0,
|
|
16
|
+
commands: args.includes('--commands') || args.length === 0,
|
|
17
|
+
hooks: args.includes('--hooks') || args.length === 0,
|
|
18
|
+
help: args.includes('--help') || args.includes('-h')
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
if (flags.help) {
|
|
22
|
+
console.log(`
|
|
23
|
+
Claude Flow Novice - Sync Script
|
|
24
|
+
|
|
25
|
+
Syncs agents, commands, and hooks from npm package to your local project.
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
npx claude-flow-novice sync [options]
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--agents Sync .claude/agents/ only
|
|
32
|
+
--commands Sync .claude/commands/ only
|
|
33
|
+
--hooks Sync config/hooks/ only
|
|
34
|
+
--force Overwrite existing files without prompting
|
|
35
|
+
--backup Create backup before syncing (recommended)
|
|
36
|
+
--help, -h Show this help message
|
|
37
|
+
|
|
38
|
+
Examples:
|
|
39
|
+
npx claude-flow-novice sync # Sync everything
|
|
40
|
+
npx claude-flow-novice sync --agents --backup # Sync agents with backup
|
|
41
|
+
npx claude-flow-novice sync --force --backup # Force sync all with backup
|
|
42
|
+
`);
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Find package location
|
|
47
|
+
const packagePath = path.join(__dirname, '..');
|
|
48
|
+
const projectRoot = process.cwd();
|
|
49
|
+
|
|
50
|
+
console.log('🚀 Claude Flow Novice - Sync Script\n');
|
|
51
|
+
console.log(`📦 Package: ${packagePath}`);
|
|
52
|
+
console.log(`📁 Project: ${projectRoot}\n`);
|
|
53
|
+
|
|
54
|
+
const syncItems = [
|
|
55
|
+
{
|
|
56
|
+
name: 'agents',
|
|
57
|
+
enabled: flags.agents,
|
|
58
|
+
source: path.join(packagePath, '.claude', 'agents'),
|
|
59
|
+
dest: path.join(projectRoot, '.claude', 'agents'),
|
|
60
|
+
description: 'Agent definitions'
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
name: 'commands',
|
|
64
|
+
enabled: flags.commands,
|
|
65
|
+
source: path.join(packagePath, '.claude', 'commands'),
|
|
66
|
+
dest: path.join(projectRoot, '.claude', 'commands'),
|
|
67
|
+
description: 'Slash commands'
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
name: 'hooks',
|
|
71
|
+
enabled: flags.hooks,
|
|
72
|
+
source: path.join(packagePath, 'config', 'hooks'),
|
|
73
|
+
dest: path.join(projectRoot, 'config', 'hooks'),
|
|
74
|
+
description: 'Validation hooks'
|
|
75
|
+
}
|
|
76
|
+
];
|
|
77
|
+
|
|
78
|
+
// Backup function
|
|
79
|
+
function createBackup(destPath) {
|
|
80
|
+
if (!fs.existsSync(destPath)) return null;
|
|
81
|
+
|
|
82
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0];
|
|
83
|
+
const backupPath = `${destPath}.backup-${timestamp}`;
|
|
84
|
+
|
|
85
|
+
console.log(` 📋 Creating backup: ${path.basename(backupPath)}`);
|
|
86
|
+
execSync(`cp -r "${destPath}" "${backupPath}"`);
|
|
87
|
+
return backupPath;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Copy directory recursively
|
|
91
|
+
function copyDir(src, dest) {
|
|
92
|
+
if (!fs.existsSync(src)) {
|
|
93
|
+
console.error(` ❌ Source not found: ${src}`);
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// Create destination directory
|
|
98
|
+
if (!fs.existsSync(dest)) {
|
|
99
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
103
|
+
let fileCount = 0;
|
|
104
|
+
|
|
105
|
+
for (const entry of entries) {
|
|
106
|
+
const srcPath = path.join(src, entry.name);
|
|
107
|
+
const destPath = path.join(dest, entry.name);
|
|
108
|
+
|
|
109
|
+
if (entry.isDirectory()) {
|
|
110
|
+
copyDir(srcPath, destPath);
|
|
111
|
+
} else {
|
|
112
|
+
fs.copyFileSync(srcPath, destPath);
|
|
113
|
+
fileCount++;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return fileCount;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Count files in directory
|
|
121
|
+
function countFiles(dir) {
|
|
122
|
+
if (!fs.existsSync(dir)) return 0;
|
|
123
|
+
|
|
124
|
+
let count = 0;
|
|
125
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
126
|
+
|
|
127
|
+
for (const entry of entries) {
|
|
128
|
+
if (entry.isDirectory()) {
|
|
129
|
+
count += countFiles(path.join(dir, entry.name));
|
|
130
|
+
} else {
|
|
131
|
+
count++;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return count;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Main sync process
|
|
139
|
+
let totalSynced = 0;
|
|
140
|
+
|
|
141
|
+
for (const item of syncItems) {
|
|
142
|
+
if (!item.enabled) continue;
|
|
143
|
+
|
|
144
|
+
console.log(`\n📂 Syncing ${item.description}...`);
|
|
145
|
+
console.log(` Source: ${item.source}`);
|
|
146
|
+
console.log(` Dest: ${item.dest}`);
|
|
147
|
+
|
|
148
|
+
// Check if source exists
|
|
149
|
+
if (!fs.existsSync(item.source)) {
|
|
150
|
+
console.log(` ⚠️ Source directory not found, skipping`);
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Backup if requested
|
|
155
|
+
if (flags.backup) {
|
|
156
|
+
createBackup(item.dest);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Check if destination exists and not forcing
|
|
160
|
+
if (fs.existsSync(item.dest) && !flags.force) {
|
|
161
|
+
const beforeCount = countFiles(item.dest);
|
|
162
|
+
console.log(` ⚠️ Destination exists with ${beforeCount} files`);
|
|
163
|
+
console.log(` 💡 Use --force to overwrite or --backup to create backup first`);
|
|
164
|
+
continue;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Perform sync
|
|
168
|
+
const fileCount = copyDir(item.source, item.dest);
|
|
169
|
+
console.log(` ✅ Synced ${fileCount} files`);
|
|
170
|
+
totalSynced += fileCount;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
console.log(`\n✨ Sync complete! ${totalSynced} files synced.\n`);
|
|
174
|
+
|
|
175
|
+
if (totalSynced > 0) {
|
|
176
|
+
console.log('Next steps:');
|
|
177
|
+
console.log(' 1. Review synced files');
|
|
178
|
+
console.log(' 2. Customize as needed for your project');
|
|
179
|
+
console.log(' 3. Commit changes to version control\n');
|
|
180
|
+
}
|
|
@@ -923,7 +923,8 @@ Execute the task using available tools. Report confidence score (0.0-1.0) at the
|
|
|
923
923
|
const MAX_TOOL_ITERATIONS = 1000; // Increased from 25 to allow comprehensive optimization tasks
|
|
924
924
|
let content = '';
|
|
925
925
|
|
|
926
|
-
// Tool use loop
|
|
926
|
+
// Tool use loop with context window management
|
|
927
|
+
const MAX_CONTEXT_MESSAGES = 20; // Keep only last 20 messages
|
|
927
928
|
while (toolUseCount < MAX_TOOL_ITERATIONS) {
|
|
928
929
|
const response = await this.anthropic.createMessage({
|
|
929
930
|
model: this.model,
|
|
@@ -979,6 +980,12 @@ Execute the task using available tools. Report confidence score (0.0-1.0) at the
|
|
|
979
980
|
});
|
|
980
981
|
|
|
981
982
|
toolUseCount++;
|
|
983
|
+
|
|
984
|
+
// Trim context window to prevent memory leak
|
|
985
|
+
if (messages.length > MAX_CONTEXT_MESSAGES) {
|
|
986
|
+
// Keep first message (initial task) + last N messages
|
|
987
|
+
messages = [messages[0], ...messages.slice(-MAX_CONTEXT_MESSAGES + 1)];
|
|
988
|
+
}
|
|
982
989
|
}
|
|
983
990
|
|
|
984
991
|
if (toolUseCount >= MAX_TOOL_ITERATIONS) {
|
|
@@ -1103,7 +1110,7 @@ Execute the task using available tools. Report confidence score (0.0-1.0) at the
|
|
|
1103
1110
|
}
|
|
1104
1111
|
|
|
1105
1112
|
/**
|
|
1106
|
-
* Recursively scan directory for .md files
|
|
1113
|
+
* Recursively scan directory for .md files (excludes node_modules)
|
|
1107
1114
|
*/
|
|
1108
1115
|
async scanAgentFiles(dirPath, basePath) {
|
|
1109
1116
|
const { promises: fs } = await import('fs');
|
|
@@ -1115,6 +1122,11 @@ Execute the task using available tools. Report confidence score (0.0-1.0) at the
|
|
|
1115
1122
|
const entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
1116
1123
|
|
|
1117
1124
|
for (const entry of entries) {
|
|
1125
|
+
// Skip node_modules to prevent memory leak
|
|
1126
|
+
if (entry.name === 'node_modules') {
|
|
1127
|
+
continue;
|
|
1128
|
+
}
|
|
1129
|
+
|
|
1118
1130
|
const fullPath = path.join(dirPath, entry.name);
|
|
1119
1131
|
|
|
1120
1132
|
if (entry.isDirectory()) {
|
package/src/index.ts
CHANGED
|
@@ -27,10 +27,10 @@ export const AgentType = {
|
|
|
27
27
|
API_DOCS: 'api-docs',
|
|
28
28
|
BACKEND_DEV: 'backend-dev',
|
|
29
29
|
FRONTEND_DEV: 'frontend-dev',
|
|
30
|
-
MOBILE_DEV: 'mobile-dev'
|
|
30
|
+
MOBILE_DEV: 'mobile-dev',
|
|
31
31
|
} as const;
|
|
32
32
|
|
|
33
|
-
export type AgentType = typeof AgentType[keyof typeof AgentType];
|
|
33
|
+
export type AgentType = (typeof AgentType)[keyof typeof AgentType];
|
|
34
34
|
|
|
35
35
|
// Version
|
|
36
36
|
export const VERSION = '2.0.4';
|
|
@@ -41,6 +41,6 @@ export const defaultConfig = {
|
|
|
41
41
|
strategy: 'development',
|
|
42
42
|
mode: 'mesh',
|
|
43
43
|
persistence: true,
|
|
44
|
-
consensusThreshold: 0.
|
|
45
|
-
gateThreshold: 0.75
|
|
44
|
+
consensusThreshold: 0.9,
|
|
45
|
+
gateThreshold: 0.75,
|
|
46
46
|
};
|