prjct-cli 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -6
- package/CLAUDE.md +442 -36
- package/README.md +47 -54
- package/bin/prjct +170 -240
- package/core/agentic/command-executor.js +113 -0
- package/core/agentic/context-builder.js +85 -0
- package/core/agentic/prompt-builder.js +86 -0
- package/core/agentic/template-loader.js +104 -0
- package/core/agentic/tool-registry.js +117 -0
- package/core/command-registry.js +106 -62
- package/core/commands.js +2030 -2211
- package/core/domain/agent-generator.js +118 -0
- package/core/domain/analyzer.js +211 -0
- package/core/domain/architect-session.js +300 -0
- package/core/{agents → infrastructure/agents}/claude-agent.js +16 -13
- package/core/{author-detector.js → infrastructure/author-detector.js} +3 -1
- package/core/{capability-installer.js → infrastructure/capability-installer.js} +3 -6
- package/core/{command-installer.js → infrastructure/command-installer.js} +4 -2
- package/core/{config-manager.js → infrastructure/config-manager.js} +4 -4
- package/core/{editors-config.js → infrastructure/editors-config.js} +2 -10
- package/core/{migrator.js → infrastructure/migrator.js} +34 -19
- package/core/{path-manager.js → infrastructure/path-manager.js} +20 -44
- package/core/{session-manager.js → infrastructure/session-manager.js} +45 -105
- package/core/{update-checker.js → infrastructure/update-checker.js} +67 -67
- package/core/{animations-simple.js → utils/animations.js} +3 -23
- package/core/utils/date-helper.js +238 -0
- package/core/utils/file-helper.js +327 -0
- package/core/utils/jsonl-helper.js +206 -0
- package/core/{project-capabilities.js → utils/project-capabilities.js} +21 -22
- package/core/utils/session-helper.js +277 -0
- package/core/{version.js → utils/version.js} +1 -1
- package/package.json +4 -12
- package/templates/agents/AGENTS.md +101 -27
- package/templates/analysis/analyze.md +84 -0
- package/templates/commands/analyze.md +9 -2
- package/templates/commands/bug.md +79 -0
- package/templates/commands/build.md +5 -2
- package/templates/commands/cleanup.md +5 -2
- package/templates/commands/design.md +5 -2
- package/templates/commands/done.md +4 -2
- package/templates/commands/feature.md +113 -0
- package/templates/commands/fix.md +41 -10
- package/templates/commands/git.md +7 -2
- package/templates/commands/help.md +2 -2
- package/templates/commands/idea.md +14 -5
- package/templates/commands/init.md +62 -7
- package/templates/commands/next.md +4 -2
- package/templates/commands/now.md +4 -2
- package/templates/commands/progress.md +27 -5
- package/templates/commands/recap.md +39 -10
- package/templates/commands/roadmap.md +19 -5
- package/templates/commands/ship.md +118 -16
- package/templates/commands/status.md +4 -2
- package/templates/commands/sync.md +19 -15
- package/templates/commands/task.md +4 -2
- package/templates/commands/test.md +5 -2
- package/templates/commands/workflow.md +4 -2
- package/core/agent-generator.js +0 -525
- package/core/analyzer.js +0 -600
- package/core/animations.js +0 -277
- package/core/ascii-graphics.js +0 -433
- package/core/git-integration.js +0 -401
- package/core/task-schema.js +0 -342
- package/core/workflow-engine.js +0 -213
- package/core/workflow-prompts.js +0 -192
- package/core/workflow-rules.js +0 -147
- package/scripts/post-install.js +0 -121
- package/scripts/preuninstall.js +0 -94
- package/scripts/verify-installation.sh +0 -158
- package/templates/agents/be.template.md +0 -27
- package/templates/agents/coordinator.template.md +0 -34
- package/templates/agents/data.template.md +0 -27
- package/templates/agents/devops.template.md +0 -27
- package/templates/agents/fe.template.md +0 -27
- package/templates/agents/mobile.template.md +0 -27
- package/templates/agents/qa.template.md +0 -27
- package/templates/agents/scribe.template.md +0 -29
- package/templates/agents/security.template.md +0 -27
- package/templates/agents/ux.template.md +0 -27
- package/templates/commands/context.md +0 -36
- package/templates/commands/stuck.md +0 -36
- package/templates/examples/natural-language-examples.md +0 -532
- /package/core/{agent-detector.js → infrastructure/agent-detector.js} +0 -0
package/core/agent-generator.js
DELETED
|
@@ -1,525 +0,0 @@
|
|
|
1
|
-
const fs = require('fs').promises
|
|
2
|
-
const path = require('path')
|
|
3
|
-
const os = require('os')
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* AgentGenerator - Dynamic agent generation for prjct-cli
|
|
7
|
-
*
|
|
8
|
-
* Generates specialized AI agents based on project analysis,
|
|
9
|
-
* customizing them with project-specific context and requirements.
|
|
10
|
-
*
|
|
11
|
-
* @version 0.5.0
|
|
12
|
-
*/
|
|
13
|
-
class AgentGenerator {
|
|
14
|
-
constructor(projectId = null) {
|
|
15
|
-
this.templatesDir = path.join(__dirname, '..', 'templates', 'agents')
|
|
16
|
-
this.projectId = projectId
|
|
17
|
-
|
|
18
|
-
// Agents are stored in global project directory, not Claude's agents
|
|
19
|
-
if (projectId) {
|
|
20
|
-
this.outputDir = path.join(os.homedir(), '.prjct-cli', 'projects', projectId, 'agents')
|
|
21
|
-
} else {
|
|
22
|
-
// Fallback for backwards compatibility (will be deprecated)
|
|
23
|
-
this.outputDir = path.join(os.homedir(), '.prjct-cli', 'agents')
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Base agents (always generated)
|
|
27
|
-
this.baseAgents = ['coordinator', 'ux', 'fe', 'be', 'qa', 'scribe']
|
|
28
|
-
|
|
29
|
-
// Agent colors for visual distinction
|
|
30
|
-
this.agentColors = {
|
|
31
|
-
coordinator: 'cyan',
|
|
32
|
-
ux: 'purple',
|
|
33
|
-
fe: 'orange',
|
|
34
|
-
be: 'yellow',
|
|
35
|
-
qa: 'green',
|
|
36
|
-
scribe: 'blue',
|
|
37
|
-
devops: 'red',
|
|
38
|
-
security: 'magenta',
|
|
39
|
-
mobile: 'pink',
|
|
40
|
-
data: 'teal',
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Generate all agents for a project
|
|
46
|
-
* @param {Object} projectAnalysis - Analysis result from /p:analyze
|
|
47
|
-
* @returns {Promise<Array>} List of generated agent types
|
|
48
|
-
*/
|
|
49
|
-
async generateAll(projectAnalysis) {
|
|
50
|
-
console.log('\n🤖 Generating AI agents...\n')
|
|
51
|
-
|
|
52
|
-
// Ensure output directory exists
|
|
53
|
-
await fs.mkdir(this.outputDir, { recursive: true })
|
|
54
|
-
|
|
55
|
-
// Detect which agents to generate
|
|
56
|
-
const conditionalAgents = this.detectConditionalAgents(projectAnalysis)
|
|
57
|
-
const allAgents = [...this.baseAgents, ...conditionalAgents]
|
|
58
|
-
|
|
59
|
-
// Generate each agent
|
|
60
|
-
const generated = []
|
|
61
|
-
for (const agentType of allAgents) {
|
|
62
|
-
try {
|
|
63
|
-
await this.generateAgent(agentType, projectAnalysis)
|
|
64
|
-
generated.push(agentType)
|
|
65
|
-
console.log(` ✅ ${agentType.toUpperCase()} agent created`)
|
|
66
|
-
} catch (error) {
|
|
67
|
-
console.error(` ❌ Failed to create ${agentType} agent:`, error.message)
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
console.log(`\n✨ Generated ${generated.length} agents\n`)
|
|
72
|
-
|
|
73
|
-
return generated
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Detect which conditional agents should be generated
|
|
78
|
-
* @param {Object} analysis - Project analysis
|
|
79
|
-
* @returns {Array<string>} List of conditional agent types
|
|
80
|
-
*/
|
|
81
|
-
detectConditionalAgents(analysis) {
|
|
82
|
-
const agents = []
|
|
83
|
-
|
|
84
|
-
// Security agent for web apps or apps with auth
|
|
85
|
-
if (
|
|
86
|
-
analysis.type === 'web' ||
|
|
87
|
-
analysis.isWebApp ||
|
|
88
|
-
analysis.hasAuth ||
|
|
89
|
-
analysis.hasAPI
|
|
90
|
-
) {
|
|
91
|
-
agents.push('security')
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
// DevOps agent for projects with Docker/K8s/CI
|
|
95
|
-
if (
|
|
96
|
-
analysis.hasDocker ||
|
|
97
|
-
analysis.hasKubernetes ||
|
|
98
|
-
analysis.hasCI ||
|
|
99
|
-
analysis.hasDeployment
|
|
100
|
-
) {
|
|
101
|
-
agents.push('devops')
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Mobile agent for React Native/Flutter/mobile frameworks
|
|
105
|
-
if (
|
|
106
|
-
analysis.isMobile ||
|
|
107
|
-
analysis.frameworks?.some(f =>
|
|
108
|
-
['react-native', 'flutter', 'ionic', 'expo'].includes(
|
|
109
|
-
f.toLowerCase(),
|
|
110
|
-
),
|
|
111
|
-
)
|
|
112
|
-
) {
|
|
113
|
-
agents.push('mobile')
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Data Science agent for ML/data projects
|
|
117
|
-
if (
|
|
118
|
-
analysis.hasML ||
|
|
119
|
-
analysis.hasDataScience ||
|
|
120
|
-
analysis.dependencies?.some(d =>
|
|
121
|
-
[
|
|
122
|
-
'tensorflow',
|
|
123
|
-
'pytorch',
|
|
124
|
-
'scikit-learn',
|
|
125
|
-
'pandas',
|
|
126
|
-
'numpy',
|
|
127
|
-
'jupyter',
|
|
128
|
-
].includes(d.toLowerCase()),
|
|
129
|
-
)
|
|
130
|
-
) {
|
|
131
|
-
agents.push('data')
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
return agents
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Generate a single agent file
|
|
139
|
-
* @param {string} type - Agent type (pm, fe, be, etc.)
|
|
140
|
-
* @param {Object} analysis - Project analysis
|
|
141
|
-
* @returns {Promise<void>}
|
|
142
|
-
*/
|
|
143
|
-
async generateAgent(type, analysis) {
|
|
144
|
-
// Load template
|
|
145
|
-
const templatePath = path.join(this.templatesDir, `${type}.template.md`)
|
|
146
|
-
let template
|
|
147
|
-
|
|
148
|
-
try {
|
|
149
|
-
template = await fs.readFile(templatePath, 'utf-8')
|
|
150
|
-
} catch (error) {
|
|
151
|
-
throw new Error(`Template not found for ${type} agent`)
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Replace placeholders
|
|
155
|
-
let content = this.replacePlaceholders(template, analysis)
|
|
156
|
-
|
|
157
|
-
// Add project-specific context
|
|
158
|
-
content += this.generateProjectContext(type, analysis)
|
|
159
|
-
|
|
160
|
-
// Write agent file
|
|
161
|
-
await fs.mkdir(this.outputDir, { recursive: true })
|
|
162
|
-
const outputPath = path.join(this.outputDir, `${type}.md`)
|
|
163
|
-
await fs.writeFile(outputPath, content, 'utf-8')
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Replace template placeholders with actual values
|
|
168
|
-
* @param {string} template - Template content
|
|
169
|
-
* @param {Object} analysis - Project analysis
|
|
170
|
-
* @returns {string} Processed template
|
|
171
|
-
*/
|
|
172
|
-
replacePlaceholders(template, analysis) {
|
|
173
|
-
const replacements = {
|
|
174
|
-
PROJECT_NAME: analysis.name || 'Unknown Project',
|
|
175
|
-
DETECTED_STACK: this.formatStack(analysis),
|
|
176
|
-
DETECTED_PATTERN: analysis.architecture || 'Not detected',
|
|
177
|
-
DETECTED_ENTRY: analysis.entryPoint || 'Not detected',
|
|
178
|
-
PROJECT_TYPE: analysis.type || 'application',
|
|
179
|
-
PRIMARY_LANGUAGE: analysis.primaryLanguage || 'JavaScript',
|
|
180
|
-
FRAMEWORK: this.formatFrameworks(analysis.frameworks),
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
let content = template
|
|
184
|
-
|
|
185
|
-
for (const [key, value] of Object.entries(replacements)) {
|
|
186
|
-
const regex = new RegExp(`\\[${key}\\]`, 'g')
|
|
187
|
-
content = content.replace(regex, value)
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
return content
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
/**
|
|
194
|
-
* Format stack information for display
|
|
195
|
-
* @param {Object} analysis - Project analysis
|
|
196
|
-
* @returns {string} Formatted stack string
|
|
197
|
-
*/
|
|
198
|
-
formatStack(analysis) {
|
|
199
|
-
const parts = []
|
|
200
|
-
|
|
201
|
-
if (analysis.primaryLanguage) {
|
|
202
|
-
parts.push(analysis.primaryLanguage)
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (analysis.frameworks && analysis.frameworks.length > 0) {
|
|
206
|
-
parts.push(...analysis.frameworks.slice(0, 3))
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (analysis.tools && analysis.tools.length > 0) {
|
|
210
|
-
parts.push(...analysis.tools.slice(0, 2))
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
return parts.length > 0 ? parts.join(' + ') : 'Not detected'
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
/**
|
|
217
|
-
* Format frameworks list
|
|
218
|
-
* @param {Array} frameworks - List of frameworks
|
|
219
|
-
* @returns {string} Formatted string
|
|
220
|
-
*/
|
|
221
|
-
formatFrameworks(frameworks) {
|
|
222
|
-
if (!frameworks || frameworks.length === 0) {
|
|
223
|
-
return 'None detected'
|
|
224
|
-
}
|
|
225
|
-
return frameworks.join(', ')
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Generate project-specific context section
|
|
230
|
-
* @param {string} type - Agent type
|
|
231
|
-
* @param {Object} analysis - Project analysis
|
|
232
|
-
* @returns {string} Context markdown
|
|
233
|
-
*/
|
|
234
|
-
generateProjectContext(type, analysis) {
|
|
235
|
-
let context = '\n\n## Project-Specific Context\n\n'
|
|
236
|
-
|
|
237
|
-
switch (type) {
|
|
238
|
-
case 'fe':
|
|
239
|
-
context += this.generateFrontendContext(analysis)
|
|
240
|
-
break
|
|
241
|
-
case 'be':
|
|
242
|
-
context += this.generateBackendContext(analysis)
|
|
243
|
-
break
|
|
244
|
-
case 'ux':
|
|
245
|
-
context += this.generateUXContext(analysis)
|
|
246
|
-
break
|
|
247
|
-
case 'qa':
|
|
248
|
-
context += this.generateQAContext(analysis)
|
|
249
|
-
break
|
|
250
|
-
case 'devops':
|
|
251
|
-
context += this.generateDevOpsContext(analysis)
|
|
252
|
-
break
|
|
253
|
-
case 'security':
|
|
254
|
-
context += this.generateSecurityContext(analysis)
|
|
255
|
-
break
|
|
256
|
-
default:
|
|
257
|
-
context += this.generateGenericContext(analysis)
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
return context
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Generate frontend-specific context
|
|
265
|
-
*/
|
|
266
|
-
generateFrontendContext(analysis) {
|
|
267
|
-
const context = []
|
|
268
|
-
|
|
269
|
-
if (analysis.frontend) {
|
|
270
|
-
const fe = analysis.frontend
|
|
271
|
-
|
|
272
|
-
if (fe.framework) {
|
|
273
|
-
context.push(`- **Framework**: ${fe.framework}${fe.version ? ` ${fe.version}` : ''}`)
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
if (fe.stateManagement) {
|
|
277
|
-
context.push(`- **State Management**: ${fe.stateManagement}`)
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
if (fe.routing) {
|
|
281
|
-
context.push(`- **Routing**: ${fe.routing}`)
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
if (fe.styling) {
|
|
285
|
-
context.push(`- **Styling**: ${fe.styling}`)
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (fe.buildTool) {
|
|
289
|
-
context.push(`- **Build Tool**: ${fe.buildTool}`)
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (fe.componentPattern) {
|
|
293
|
-
context.push(`- **Component Pattern**: ${fe.componentPattern}`)
|
|
294
|
-
}
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
if (analysis.directories?.components) {
|
|
298
|
-
context.push(`- **Components Location**: ${analysis.directories.components}`)
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
return context.length > 0 ? context.join('\n') : '- No specific frontend context detected'
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Generate backend-specific context
|
|
306
|
-
*/
|
|
307
|
-
generateBackendContext(analysis) {
|
|
308
|
-
const context = []
|
|
309
|
-
|
|
310
|
-
if (analysis.backend) {
|
|
311
|
-
const be = analysis.backend
|
|
312
|
-
|
|
313
|
-
if (be.framework) {
|
|
314
|
-
context.push(`- **Framework**: ${be.framework}${be.version ? ` ${be.version}` : ''}`)
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
if (be.database) {
|
|
318
|
-
context.push(`- **Database**: ${be.database}`)
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
if (be.orm) {
|
|
322
|
-
context.push(`- **ORM/ODM**: ${be.orm}`)
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
if (be.auth) {
|
|
326
|
-
context.push(`- **Authentication**: ${be.auth}`)
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
if (be.apiStyle) {
|
|
330
|
-
context.push(`- **API Style**: ${be.apiStyle}`)
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
if (analysis.hasAPI) {
|
|
335
|
-
context.push(`- **API Detected**: Yes`)
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
return context.length > 0 ? context.join('\n') : '- No specific backend context detected'
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
/**
|
|
342
|
-
* Generate UX-specific context
|
|
343
|
-
*/
|
|
344
|
-
generateUXContext(analysis) {
|
|
345
|
-
const context = []
|
|
346
|
-
|
|
347
|
-
if (analysis.frontend?.styling) {
|
|
348
|
-
context.push(`- **Design System**: ${analysis.frontend.styling}`)
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
if (analysis.hasDesignSystem) {
|
|
352
|
-
context.push(`- **Design System Files**: Detected`)
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
if (analysis.accessibility) {
|
|
356
|
-
context.push(`- **Accessibility**: ${analysis.accessibility}`)
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
context.push(`- **Focus**: User experience, visual design, interaction patterns`)
|
|
360
|
-
|
|
361
|
-
return context.join('\n')
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Generate QA-specific context
|
|
366
|
-
*/
|
|
367
|
-
generateQAContext(analysis) {
|
|
368
|
-
const context = []
|
|
369
|
-
|
|
370
|
-
if (analysis.testing) {
|
|
371
|
-
if (analysis.testing.framework) {
|
|
372
|
-
context.push(`- **Test Framework**: ${analysis.testing.framework}`)
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
if (analysis.testing.coverage) {
|
|
376
|
-
context.push(`- **Coverage Tool**: ${analysis.testing.coverage}`)
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
if (analysis.testing.e2e) {
|
|
380
|
-
context.push(`- **E2E Testing**: ${analysis.testing.e2e}`)
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
if (analysis.hasTests) {
|
|
385
|
-
context.push(`- **Tests Detected**: Yes`)
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
return context.length > 0 ? context.join('\n') : '- No specific testing context detected'
|
|
389
|
-
}
|
|
390
|
-
|
|
391
|
-
/**
|
|
392
|
-
* Generate DevOps-specific context
|
|
393
|
-
*/
|
|
394
|
-
generateDevOpsContext(analysis) {
|
|
395
|
-
const context = []
|
|
396
|
-
|
|
397
|
-
if (analysis.hasDocker) {
|
|
398
|
-
context.push(`- **Docker**: Detected (Dockerfile, docker-compose)`)
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
if (analysis.hasKubernetes) {
|
|
402
|
-
context.push(`- **Kubernetes**: Detected`)
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
if (analysis.hasCI) {
|
|
406
|
-
context.push(`- **CI/CD**: ${analysis.ciProvider || 'Detected'}`)
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
if (analysis.deployment) {
|
|
410
|
-
context.push(`- **Deployment**: ${analysis.deployment}`)
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
return context.length > 0 ? context.join('\n') : '- Infrastructure and deployment files detected'
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
/**
|
|
417
|
-
* Generate security-specific context
|
|
418
|
-
*/
|
|
419
|
-
generateSecurityContext(analysis) {
|
|
420
|
-
const context = []
|
|
421
|
-
|
|
422
|
-
if (analysis.hasAuth) {
|
|
423
|
-
context.push(`- **Authentication**: Detected`)
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
if (analysis.hasAPI) {
|
|
427
|
-
context.push(`- **API Security**: Focus on endpoint security`)
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
if (analysis.type === 'web' || analysis.isWebApp) {
|
|
431
|
-
context.push(`- **Web Security**: OWASP Top 10 compliance`)
|
|
432
|
-
}
|
|
433
|
-
|
|
434
|
-
context.push(`- **Focus**: Security audits, vulnerability assessment, secure coding practices`)
|
|
435
|
-
|
|
436
|
-
return context.join('\n')
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Generate generic project context
|
|
441
|
-
*/
|
|
442
|
-
generateGenericContext(analysis) {
|
|
443
|
-
const context = []
|
|
444
|
-
|
|
445
|
-
if (analysis.description) {
|
|
446
|
-
context.push(`- **Description**: ${analysis.description}`)
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
if (analysis.mainDirectories && analysis.mainDirectories.length > 0) {
|
|
450
|
-
context.push(`- **Main Directories**: ${analysis.mainDirectories.join(', ')}`)
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
if (analysis.totalFiles) {
|
|
454
|
-
context.push(`- **Total Files**: ${analysis.totalFiles}`)
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
return context.length > 0 ? context.join('\n') : '- Standard project setup'
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Update existing agents with new project context
|
|
462
|
-
* @param {Object} analysis - Updated project analysis
|
|
463
|
-
* @returns {Promise<Array>} List of updated agents
|
|
464
|
-
*/
|
|
465
|
-
async updateExistingAgents(analysis) {
|
|
466
|
-
console.log('\n🔄 Updating existing agents...\n')
|
|
467
|
-
|
|
468
|
-
const updated = []
|
|
469
|
-
|
|
470
|
-
// Check which agents currently exist
|
|
471
|
-
try {
|
|
472
|
-
const files = await fs.readdir(this.outputDir)
|
|
473
|
-
const agentFiles = files.filter(f => f.endsWith('.md') && !f.startsWith('.'))
|
|
474
|
-
|
|
475
|
-
for (const file of agentFiles) {
|
|
476
|
-
const type = file.replace('.md', '')
|
|
477
|
-
|
|
478
|
-
try {
|
|
479
|
-
await this.generateAgent(type, analysis)
|
|
480
|
-
updated.push(type)
|
|
481
|
-
console.log(` ↻ ${type.toUpperCase()} agent updated`)
|
|
482
|
-
} catch (error) {
|
|
483
|
-
console.error(` ❌ Failed to update ${type} agent:`, error.message)
|
|
484
|
-
}
|
|
485
|
-
}
|
|
486
|
-
} catch (error) {
|
|
487
|
-
console.error('Error reading agents directory:', error.message)
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
console.log(`\n✨ Updated ${updated.length} agents\n`)
|
|
491
|
-
|
|
492
|
-
return updated
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
/**
|
|
496
|
-
* Remove agents that are no longer needed
|
|
497
|
-
* @param {Array} requiredAgents - List of agents that should exist
|
|
498
|
-
* @returns {Promise<Array>} List of removed agents
|
|
499
|
-
*/
|
|
500
|
-
async cleanupObsoleteAgents(requiredAgents) {
|
|
501
|
-
const removed = []
|
|
502
|
-
|
|
503
|
-
try {
|
|
504
|
-
const files = await fs.readdir(this.outputDir)
|
|
505
|
-
const agentFiles = files.filter(f => f.endsWith('.md') && !f.startsWith('.'))
|
|
506
|
-
|
|
507
|
-
for (const file of agentFiles) {
|
|
508
|
-
const type = file.replace('.md', '')
|
|
509
|
-
|
|
510
|
-
if (!requiredAgents.includes(type)) {
|
|
511
|
-
const filePath = path.join(this.outputDir, file)
|
|
512
|
-
await fs.unlink(filePath)
|
|
513
|
-
removed.push(type)
|
|
514
|
-
console.log(` 🗑️ ${type.toUpperCase()} agent removed (no longer needed)`)
|
|
515
|
-
}
|
|
516
|
-
}
|
|
517
|
-
} catch (error) {
|
|
518
|
-
console.error('Error during cleanup:', error.message)
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
return removed
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
|
|
525
|
-
module.exports = AgentGenerator
|